网络编程 - BIO

网络编程中,服务端提供IP和监听端口,客户端经过服务端的IP和端口发送请求,进行通讯。这篇是讲传统的同步阻塞模型--BIO。java

客户端

BioClient主要是建立一个Socket,并经过Socket把请求发送服务端,代码以下:编程

public class BioClient {
    public static void main(String[] args) {
        try {
            // 经过服务IP,端口建立一个Socket
            Socket socket = new Socket(Const.IP, Const.PORT);
            // 获取Socket输出流
            OutputStream outputStream = socket.getOutputStream();
            // 输出流
            outputStream.write("hello world".getBytes());
            // 关闭流
            outputStream.close();
            // 关闭Socket
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端

服务端先建立一个ServerSocket,用于监听指定端口的链接请求。accept方法会一直阻塞,直到新的链接创建,创建后,建立一个Socket与客户端进行通讯。在读取输入流的时候,br.readLine()也是阻塞的。服务器

public class BioServer {
    public static void main(String[] args) {
        try {
            //获取ServerSocket,绑定服务器的端口
            ServerSocket serverSocket = new ServerSocket(Const.PORT);
            while (true) {
                // 建立一个Socket接收链接
                Socket socket = serverSocket.accept();
                // 获取输入流
                InputStream inputStream = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                String message;
                while (null != (message = br.readLine())) {
                    System.out.println(message);
                }
                // 关闭流
                inputStream.close();
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上面的实例中,有个比较大的缺点,就是同时只能处理一个链接,要想处理多个并发客户端,咱们能够简单地用多线程来管理,每次有新的sockert,建立一个线程或则放入线程池来处理。
咱们把sockert的部分抽出来:网络

public class BioServerHandler implements Runnable {
    private Socket socket;

    public BioServerHandler(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            // 获取输入流
            InputStream inputStream = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            String message;
            while (null != (message = br.readLine())) {
                System.out.println(message);
            }
            // 关闭流
            inputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

建立线程的方式:多线程

public class BioServer2 {
    public static void main(String[] args) {
        try {
            //获取ServerSocket,绑定服务器的端口
            ServerSocket serverSocket = new ServerSocket(Const.PORT);
            while (true) {
                // 建立一个Socket接收链接
                Socket socket = serverSocket.accept();
                new Thread(new BioServerHandler(socket)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

建立线程池的方式:并发

public class BioServer3 {
    private static ExecutorService executorService
            = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
        try {
            //获取ServerSocket,绑定服务器的端口
            ServerSocket serverSocket = new ServerSocket(Const.PORT);
            while (true) {
                // 建立一个Socket接收链接
                Socket socket = serverSocket.accept();
                executorService.execute(new BioServerHandler(socket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BioServer2和BioServer3经过线程,能够比BioServer同时处理更多的客户端请求,可是依然存在着不足:在任什么时候候,都有大量的线程处于休眠状态,只能等待输入或则输出数据就绪,浪费资源。为此,java提供了另一直方式-NIO。socket

相关文章
相关标签/搜索