一、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
微信扫一扫
支付宝扫一扫