BIO -- 同步阻塞的编程方式

BIO编程方式通常是在JDK1.4版本之前常用的编程方式

一、编程实现的过程:

  先在服务端启动一个ServerSocket来监听网络请求,客户端启动Socket发起网络请求,默认情况下ServerSocket会建立一个线程来处理此请求,如果服务端没有线程可用,客户端则会阻塞等待或者遭到拒绝,并且建立好的连接,在通信过程中是同步的,在并发处理上效率较低;

在这里插入图片描述
  同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,也可以通过线程池机制改善
  BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用之中,是JDK1.4之前的唯一选择,但程序直观简单;

二、BIO编程步骤
  • Server:

    • 创建ServerSocket实例;
    • 绑定占用端口;
    • 通过accept()方法监听并等待客户端的连接;
    • 如果有客户端连接则会返回一个socket实例;
    • 通过socket实例进行读写操作;
    • 关闭占用资源和socket;

代码:(单线程)

public class BIOServer {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket实例
        ServerSocket socket = new ServerSocket();
        //绑定端口
        System.out.println("服务端启动");
        socket.bind(new InetSocketAddress(666));
        //监听等待客户端的连接,会阻塞直至用户端的连接
        boolean flg = false;
        while (true) {
            Socket socket1 = socket.accept();
            //进行通信
            //读操作流
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(socket1.getInputStream()));
                OutputStream outputStream = socket1.getOutputStream();
                String msg = null;
                while ((msg = reader.readLine()) != null) {
                    System.out.println(msg);
                    outputStream.write(msg.getBytes());
                    outputStream.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭流
                try {
                    reader.close();
                    socket1.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }    
        }
    }
}

  • Client

    • 创建Socket实例;
    • 通过connect()连接服务端;
    • 进行读写操作;
    • 关闭资源;

代码:

public class BIOClient {
    public static void main(String[] args) throws IOException {
        //客户端创建socket实例
        Socket socket = new Socket();
        //连接服务端
        InetSocketAddress inetSocketAddress = new InetSocketAddress(666);
        socket.connect(inetSocketAddress);
        System.out.println("客户端连接成功");
        //读写操作
        OutputStream outputStream = socket.getOutputStream();
        InputStream inputStream = socket.getInputStream();

        Scanner scanner = new Scanner(System.in);
        scanner.useDelimiter("\n");

        while (scanner.hasNext()) {
            //接收键盘输入
            String nextLine = scanner.nextLine();
            //发送操作
            outputStream.write((nextLine + "\n").getBytes());
            //接收服务端返回
            byte[] bytes = new byte[1024];
            int read = inputStream.read(bytes);
            String revc = new String(bytes,0,read);
            System.out.println("revc :" + revc);

            if ("exit".equals(nextLine)) {
                break;
            }
        }
        outputStream.close();
        scanner.close();
        socket.close();
    }
}

  可以使用线程池对Server端代码进行优化,这里没有使用线程池而是手动创建一个子线程处理新用户的连接;
在这里插入图片描述

package network.BIO;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @Author Daria
 * @Description
 * @Date 2019/5/18 -- 11:18
 */
class MyThread implements Runnable {
    Socket socket;
    public MyThread(Socket socket) { //将主线程拿到的socket实例交给子线程
        this.socket = socket;
    }
    @Override
    public void run() {
        System.out.println("有新用户连接" + Thread.currentThread().getName() );
        //进行通信
        //读操作流
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            OutputStream outputStream = this.socket.getOutputStream();
            String msg = null;
            while ((msg = reader.readLine()) != null) {
                System.out.println(msg);
                outputStream.write(msg.getBytes());
                outputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                reader.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public class BIOServer {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket实例
        ServerSocket socket = new ServerSocket();
        //绑定端口
        System.out.println("服务端启动");
        socket.bind(new InetSocketAddress(666));
        //监听等待客户端的连接,会阻塞直至用户端的连接
        boolean flg = false;
        while (true) {
            Socket socket1 = socket.accept();
            new Thread(new MyThread(socket1)).start(); //可以new Thread类,也可以使用λ表达式
            /*new Thread(()-> {
                System.out.println("有新用户连接" );
                //进行通信
                //读操作流
                BufferedReader reader = null;
                try {
                    reader = new BufferedReader(new InputStreamReader(socket1.getInputStream()));
                    OutputStream outputStream = socket1.getOutputStream();
                    String msg = null;
                    while ((msg = reader.readLine()) != null) {
                        System.out.println(msg);
                        outputStream.write(msg.getBytes());
                        outputStream.flush();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    //关闭流
                    try {
                        reader.close();
                        socket1.close();
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();*/
        }
    }
}

三、测试

启动Server端后打开两个Client
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Daria_/article/details/92794170
BIO
今日推荐