0
我想知道用一個線程和一個緩衝區實現多用戶NIO服務器的最佳方法。目前我使用選擇器來實現這一點,但我只想到如何閱讀所有的客戶端。我在使用一個緩衝區實現寫入時遇到了問題。我是否需要第二個寫入緩衝區?或者我必須(不幸)每個客戶端都有一個寫緩衝區?我寫這個例子很容易展示我如何做事,只是爲了讓你知道所有的處理都發生在調度器的線程中,我不會通過另一個線程與任何狀態進行交互!One thread one ByteBuffer NIO
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ServerSocketChannel server = ServerSocketChannel.open();
Selector selector = Selector.open();
ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
Map<SelectionKey, SocketChannel> clients = new HashMap<>();
server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);
server.bind(new InetSocketAddress(43594));
scheduler.scheduleAtFixedRate(() -> {
try {
selector.selectNow();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (key.isAcceptable()) {
for (int i = 0; i < 16; i++) {
SocketChannel client = server.accept();
if (client == null)
break;
client.configureBlocking(false);
SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ);
clients.put(clientKey, client);
}
}
if (key.isReadable()) {
SocketChannel client = clients.get(key);
if (client != null) {
buffer.clear();
client.read(buffer);
buffer.flip();
// do stuff with buffer
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}, 600, 600, TimeUnit.MILLISECONDS);
您確定嗎?我目前的實現適用於許多客戶端,雖然我沒有處理部分讀取或寫入。你是否知道如何做到這一點的完整例子?我想在我的應用程序中最小化垃圾創建。 – Jire
您當前的實現'工作'*是因爲*您尚未處理部分讀取或寫入操作。在你實現它的那一刻,你會意識到你需要每個通道有一個或兩個緩衝區來保存待處理數據。這當然很明顯?緩衝區或通道不會強加任何Gc負載,因爲它持續的時間與連接一樣長,在任何情況下,您的主要擔憂都必須是正確的。你可以在零時間得到錯誤的答案。這沒有關係或興趣。 – EJP
謝謝你的迴應,它清理了一些東西。我想共享我的緩衝區以節省垃圾,有什麼建議嗎?另外我懷疑附件的效率。我意識到他們可以簡化我的代碼,並且可能(?)通過引入上下文來消除對我的客戶端映射的需求。雖然這款遊戲需要在少量硬件上運行數千個客戶端,但我並沒有進行實時開發。如果有幫助,系統基於每600毫秒發送一次消息。 – Jire