一、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/zh-hant/n/331840.html
微信掃一掃
支付寶掃一掃