Open Source, Open Future!
  menu
107 文章
ღゝ◡╹)ノ❤️

网络编程---服务器模型

单线程阻塞

        ServerSocket serverSocket = new ServerSocket(7788);
        while (true) {
            Socket socket = serverSocket.accept();
            handle(socket);
        }

1.jpeg

连接数:线程数 = n:1
优势:最简单的服务器模型,只有一个线程,开销小
劣势:只能串行处理

多线程阻塞

    public static void main(String[] args) {
        ServerSocket serverSocket = new ServerSocket(7788);
        while (true) {
            Socket socket = serverSocket.accept();
            Thread t = new Thread(new Handle(socket));
            t.start();
        }
    }

2.png

连接数:线程数 = 1:1
优势:支持并发处理
劣势:开销大;如果大量的线程都处在等待状态,浪费资源

多线程阻塞(线程池)

连接数:线程数 = n:m

单Reactor单线程

        // 创建选择器
        Selector selector = Selector.open();
        // 非阻塞模式
        channel.configureBlocking(false);
        // 注册通道,关注读事件
        SelectionKey selectionKey = channel.register(selector, SelectionKey.OP_READ);
        while (true) {
            // select()方法返回的int值表示有多少通道已经就绪
            int readyChannels = selector.select();
            if (readyChannels == 0) {
                continue;
            }
            // 访问所有的已就绪的通道
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator keyIterator = selectedKeys.iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = (SelectionKey) keyIterator.next();
                if (key.isAcceptable()) {
                } else if (key.isConnectable()) {
                } else if (key.isReadable()) {
                } else if (key.isWritable()) {
                }
                // Selector不会自动从集合中移除key实例。必须在处理完通道时自己移除
                // 下次该通道变成就绪时,Selector会再次将其放入已选择键集中
                keyIterator.remove();
            }
        }

原理图:

3.jpeg

说明:当客户端往套接字发送数据时,内核层从网卡接收数据后会调用回调函数,然后维护一个事件列表,应用层获取这个列表即可得到所有感兴趣的事件。

模型图:

image.png

优势:用一个线程就可实现对多个连接的管理,不会因为某个连接阻塞导致其他连接无法处理,提高了服务器的执行效率。

单Reactor多线程

image.png

将最耗时的业务逻辑处理交给线程池处理。

主从Reactor多线程

image.png

优势:充分利用服务器的多核,并发处理能力更高。