[英]Java NIO inherent flaw in reading from one socket and writing to another?
我正在研究基本的最小服務器概念,使用NIO和套接字通道將數據從一個端口流向另一個目的地。
事情在全速,快速鏈接等方面都很有效。當一方比另一方快時,事情會非常糟糕並消耗大量的CPU。 事情很有效,工作效率很低。
例:
Iterator keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = (SelectionKey) keys.next();
keys.remove();
try {
if (!key.isValid()) continue;
if (key.isReadable()) read(key);
}
catch (Exception e) {
e.printStackTrace();
key.cancel();
}
}
只要套接字具有可讀取的數據,就會發生讀取調用。 但是,如果因為客戶端具有高延遲或者沒有快速讀取數據而無法寫入此套接字的可寫部分,該怎么辦? 我們最終以瘋狂的速度循環,直到更多可寫緩沖區釋放為止:
public void read(SelectionKey key) throws IOException {
ByteBuffer b = (ByteBuffer) buffers.get(readable); //prior buffer that may or may not have been fully used from the prior write attempt
int bytes_read = readable.read(b);
b.flip();
if (bytes_read > 0 || b.position() > 0) writeable.write(b);
b.compact();
}
所以說我們可以從千兆位讀取套接字,但是接收器只能從100kilobit讀取我們的可寫套接字....我們可能在我們可以寫入客戶端的每一小塊數據之間循環一百萬次,因為它們只是不會像我們想要的那樣快地消耗套接字緩沖區中的數據。
如果我使用Thread執行此操作,則不會出現問題,因為我們會在寫入調用時阻塞。 但是對於NIO,你應該怎樣做才能讓它跳過閱讀通知?
我想通了。 我仍然沒有找到指向我的文檔,但在考慮了更多的事情后,我意識到這就是OP_WRITEABLE場景的用途。
因此,當可寫入返回它接受0字節時,我在可讀通道上注銷OP_READ,並在可寫通道上注冊OP_WRITEABLE。 一旦我收到通知它可寫,我就交換了讀/寫通道,包括現在注冊掉OP_WRITEABLE的內容。
因此,當無法完成寫操作時,取消注冊觸發您嘗試寫入的讀取,並在其上注冊寫入通知。 一旦你得到它,交換注冊。
事情現在很好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.