Java 网络编程 阻塞与非阻塞

阻塞模式体会(单线程阻塞只能干一件事)

服务器代码

public class Server {
    public static void main(String[] args) throws Exception {
        //创建服务器
        ServerSocketChannel ssc = ServerSocketChannel.open();
        //给服务器绑定端口号,以便客户端找到服务器
        ssc.bind(new InetSocketAddress(8080));
        //创建List集合来装多个客户端同时发来的消息
        List<SocketChannel> list = new ArrayList<>();
        //服务器进行工作
        while (true){
            System.out.println("等待连接!");
            //获取客户段发来的连接
            SocketChannel sc = ssc.accept();//这是阻塞模式 线程在此处停止
            System.out.println("连接成功!"+sc.getRemoteAddress());
            list.add(sc);
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(32);//分配缓冲区
            for (SocketChannel socketChannel : list) {
                System.out.println("等待客户端的数据输出!");
                socketChannel.read(byteBuffer);//这是阻塞模式 线程在此处停止
                byteBuffer.flip();
                System.out.println(StandardCharsets.UTF_8.decode(byteBuffer).toString());
                byteBuffer.clear();
            }
        }
    }
}

客户端代码

public class Client {
    public static void main(String[] args) throws Exception {
        SocketChannel sc = SocketChannel.open();
        sc.connect(new InetSocketAddress("localhost",8080));
        System.out.println("我开始发送数据");
    }
}

体会结果

客户端程序没有启动 accept()方法被阻塞,线程停止

 客户端程序debug启动 没有数据输出!此时read()方法被阻塞,线程停止

 客户端程序写入数据!服务器继续往下执行等待下一次的链接

 但是这时客户端再次写数据,服务器没有响应。

 若在这时再开启一个客户端线程连接服务器(之前的操作的有点失误,重新来了一遍端口号变了)

但是结果还是一样的,在list集合中我们保存了第一个客户端的连接,所以上此图的第二次写的内容在第二个客户端连接的时候,就会被执行。

 非阻塞模式(单线程做牛做马)

服务器代码(socketChannel.configureBlocking(false))

public class Server {
    public static void main(String[] args) throws Exception {
        //创建服务器
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);//设置非阻塞
        //给服务器绑定端口号,以便客户端找到服务器
        ssc.bind(new InetSocketAddress(8080));
        //创建List集合来装多个客户端同时发来的消息
        List<SocketChannel> list = new ArrayList<>();
        //服务器进行工作
        while (true){
            Thread.sleep(1000);
            System.out.println("等待连接!");
            //获取客户段发来的连接
            SocketChannel sc = ssc.accept();//这是非阻塞模式 返回值null;继续往下执行
            if (sc != null){
                sc.configureBlocking(false);
                System.out.println("连接成功!"+sc.getRemoteAddress());
                list.add(sc);
                Thread.sleep(1000);
            }
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(32);//分配缓冲区
            for (SocketChannel socketChannel : list) {
                System.out.println("等待客户端的数据输出!");
                socketChannel.read(byteBuffer);//这是非阻塞模式 返回值0
                byteBuffer.flip();
                System.out.println(StandardCharsets.UTF_8.decode(byteBuffer).toString());
                byteBuffer.clear();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_57533658/article/details/130000220