Socket编程中的阻塞和非阻塞模式有何区别?代码举例讲解

Socket编程中,阻塞模式和非阻塞模式的主要区别在于:

阻塞模式:

  • 当进行读/写操作时,线程会被阻塞,直到操作完成才返回。
  • 需要维护较少的状态和逻辑,编程相对简单。
  • 当连接异常或无数据可读/写时,线程会一直阻塞,影响程序的响应性。

非阻塞模式:

  • 当进行读/写操作时,线程会立即返回,无需等待操作完成。
  • 需要维护较复杂的状态和逻辑,实现相对复杂。
  • 当连接异常或无数据可读/写时,线程不会阻塞,有利于构建响应性高的程序。

对应的Java API有:

阻塞:

  • Socket类及其方法(accept()、getInputStream()等)

非阻塞:

  • SocketChannel类及其方法(read()、write()等)
  • Selector类:用于监听多个Channel的事件

阻塞模式示例:

public class BlockingSocketDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8000);
        Socket socket = serverSocket.accept();

        InputStream input = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int read = input.read(bytes);
        while (read != -1) {
            // 处理读取的数据
            read = input.read(bytes); 
        }
    } 
}

非阻塞模式示例:

public class NonBlockingSocketDemo {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.bind(new InetSocketAddress(8000));
        serverChannel.configureBlocking(false);

        Selector selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            int keys = selector.select();
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            for (SelectionKey key : selectedKeys) {
                // 处理Channel事件,例如接受连接、读取数据等
            }
        }
    }
}