ServerSocketChannel介绍与应用

一、ServerSocketChannel概述

ServerSocketChannel是Java NIO提供的一种与传统IO不同的新型I/O Channel,它可以同时处理多个客户端请求。通常它会被用于服务端程序,监听客户端的连接请求,并创建相应的SocketChannel进行处理。

import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class ServerSocketChannelDemo {
    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8080));
        while (true) {
            SocketChannel socketChannel = serverSocketChannel.accept();
            //处理客户端请求
        }
    }
}

二、ServerSocketChannel与SocketChannel的区别

ServerSocketChannel和SocketChannel都是Java NIO提供的I/O Channel,但是它们的用途不同。ServerSocketChannel被用于监听客户端连接请求,而SocketChannel则是客户端与服务端进行通信的通道。

ServerSocketChannel是一个单向的Channel,只能接收连接,而不能发送数据。而SocketChannel则是一个双向的Channel,既可以发送数据,也可以接收数据。

三、ServerSocketChannel的非阻塞模式

ServerSocketChannel可以通过设置非阻塞模式来提高处理效率。在非阻塞模式下,当没有客户端连接请求时,它不会一直等待,而是会直接返回null,程序可以继续运行。因此,在while循环中,需要对返回的SocketChannel进行非空判断。

import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class ServerSocketChannelDemo {
    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.socket().bind(new InetSocketAddress(8080));
        while (true) {
            SocketChannel socketChannel = serverSocketChannel.accept();
            if (socketChannel != null) {
                //处理客户端请求
            }
        }
    }
}

四、ServerSocketChannel的Selector选择器

ServerSocketChannel的重要特性是可以组合Selector选择器一起使用,从而可以同时管理多个客户端的请求。它可以将所有的SocketChannel注册到同一个Selector中,当有连接请求时,Selector会通知相关的SocketChannel进行处理。

import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class SelectorServerSocketChannelDemo {
    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.socket().bind(new InetSocketAddress(8080));
        
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        
        while (true) {
            selector.select();
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            for (SelectionKey selectionKey : selectionKeys) {
                if (selectionKey.isAcceptable()) {
                    ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
                    SocketChannel socketChannel = ssc.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (selectionKey.isReadable()) {
                    SocketChannel channel = (SocketChannel) selectionKey.channel();
                    //读取客户端数据
                }
            }
            selectionKeys.clear();
        }
    }
}

五、ServerSocketChannel的多线程应用

ServerSocketChannel同样可以通过多线程的方式进行应用,采用线程池可以使程序更高效地处理多个客户端连接请求。在每个线程中,可以针对每个客户端创建一个SocketChannel进行处理。

import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolServerSocketChannelDemo {
    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8080));
        
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        
        while (true) {
            SocketChannel socketChannel = serverSocketChannel.accept();
            executorService.execute(new SocketChannelHandler(socketChannel));
        }
    }
}

class SocketChannelHandler implements Runnable {
    private SocketChannel socketChannel;

    public SocketChannelHandler(SocketChannel socketChannel) {
        this.socketChannel = socketChannel;
    }

    public void run() {
        //处理客户端请求
    }
}

原创文章,作者:PJPRR,如若转载,请注明出处:https://www.506064.com/n/331840.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
PJPRR的头像PJPRR
上一篇 2025-01-20 14:11
下一篇 2025-01-20 14:11

发表回复

登录后才能评论