[英]Java - how can I check if the ServerSocket.accept()ed the connection?
[英]How can I avoid blocking with Java ServerSocket?
我正在研究一個套接字監聽器,它必須在2個端口上偵聽2種類型的數據(端口80和端口81)。 這些數據與對數據執行的操作類型非常相似,只是因為它們到達不同的端口而不同。 我繼續使用Java的ServerSocket類編寫實現,但后來才意識到ServerSocket類的accept()方法是塊,我的實現無法承受。 所以現在我正在考慮使用Java NIO實現相同的功能,但在完成了一些教程之后,我認為我比我開始時更困惑。 如果這里的某個人可以引導我完成整個過程,即使它是偽代碼或技術“下一步該做什么”,那將是很棒的。 這就是我打算實現的目標。
通過調用2個類似的線程來監聽,就像永遠在2個端口上一樣。(非阻塞)來自某個網絡位置的遠程設備連接,發送數據然后斷開連接。
我想如果只知道如何使用NIO設置服務器來監聽端口,那么就可以實現localhost上的端口80,其余的都很容易實現。
干杯
這里有一個開始使用NIO的小例子。
它是一個偵聽端口80和81的服務器,並打印標准輸出上接收的所有內容。 收到以CLOSE
開頭的數據包后CLOSE
; 收到以QUIT
開頭的數據包后,整個服務器都會關閉。 缺少發送部分和錯誤處理可能會好一點。 :-)
public static void main() throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(1024);
Selector selector = Selector.open();
ServerSocketChannel server1 = ServerSocketChannel.open();
server1.configureBlocking(false);
server1.socket().bind(new InetSocketAddress(80));
server1.register(selector, OP_ACCEPT);
ServerSocketChannel server2 = ServerSocketChannel.open();
server2.configureBlocking(false);
server2.socket().bind(new InetSocketAddress(81));
server2.register(selector, OP_ACCEPT);
while (true) {
selector.select();
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SocketChannel client;
SelectionKey key = iter.next();
iter.remove();
switch (key.readyOps()) {
case OP_ACCEPT:
client = ((ServerSocketChannel) key.channel()).accept();
client.configureBlocking(false);
client.register(selector, OP_READ);
break;
case OP_READ:
client = (SocketChannel) key.channel();
buffer.clear();
if (client.read(buffer) != -1) {
buffer.flip();
String line = new String(buffer.array(), buffer.position(), buffer.remaining());
System.out.println(line);
if (line.startsWith("CLOSE")) {
client.close();
} else if (line.startsWith("QUIT")) {
for (SelectionKey k : selector.keys()) {
k.cancel();
k.channel().close();
}
selector.close();
return;
}
} else {
key.cancel();
}
break;
default:
System.out.println("unhandled " + key.readyOps());
break;
}
}
}
}
Obs : SelectionKey
( OP_ACCEPT
...)的字段是靜態導入的:
import static java.nio.channels.SelectionKey.*;
當您需要擴展到數千個同時連接時,需要NIO。
否則,我建議使用多個線程。 對於每個端口(及其對應的ServerSocket
),創建一個在循環中調用accept()
的線程。 這些調用會阻塞,但這沒關系,因為其他線程正在運行,負責任何可用的任務。
接受新Socket
,創建專用於該連接的另一個線程。 它取決於應用程序,但通常此線程將從套接字讀取(阻塞操作),並執行請求的操作,將結果寫回套接字。
在大多數桌面平台上,此體系結構將擴展到數百個連接。 編程模型非常簡單,只要每個連接都是獨立的並且獨立於其他連接(這可以避免並發問題)。 引入NIO將提供更多可擴展性,但需要很多復雜性。
許多框架,例如Apache MINA和Netty ,都是基於Java NIO實現的,以增強非阻塞IO編程。 我強烈建議他們讓你的NIO編程變得快樂,而不是噩夢。 他們適合你的問題。
此外,嘗試在傳輸消息大小和編碼/解碼(序列化/反序列化)性能中使用有效的協議。 Google Protocol Buffers是該領域的可靠解決方案。 還可以看看Kryo和KryoNet 。 他們可以提供幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.