簡體   English   中英

java nio ServerSocketChannel如何接受?

[英]How java nio ServerSocketChannel accept works?

我無法理解NIO是如何在幕后工作的。 這是一個示例代碼:

// Create the server socket channel
ServerSocketChannel server = ServerSocketChannel.open();
// nonblocking I/O
server.configureBlocking(false);
// host-port 8000
server.socket().bind(new java.net.InetSocketAddress(host,8000));

// Create the selector
Selector selector = Selector.open();
// Recording server to selector (type OP_ACCEPT)
server.register(selector,SelectionKey.OP_ACCEPT);

while (true) {
      selector.select(); // blocking operation
      Iterator it = selector.selectedKeys().iterator();
      while (it.hasNext()) {
        SelectionKey selKey = (SelectionKey) it.next();

        // THE MOST INTRIGUING PART HERE!!!
        if (selKey.isAcceptable()) {
          ServerSocketChannel ssChannel = (ServerSocketChannel) selKey.channel();
          SocketChannel sc = ssChannel.accept();
        }
        it.remove();
     }
}

在這里,我有幾個問題:

  1. selKey.channel()返回一個ServerSocketChannel它與我們在使用ServerSocketChannel.open()開始創建時完全相同嗎? 如果沒有,那么它是什么?
  2. 更重要的問題:在大多數其他教程中selKey.channel(); 跳過步驟,他們只使用SocketChannel client = server.accept(); 例如: http//www.onjava.com/pub/a/onjava/2002/09/04/nio.html? page = 2 ,此處: http//www.developer.com/java/article。 php / 10922_3837316_2 / Non-Blocking-IO-Made-Possible-in-Java.htm那么,server.accept()如何知道我們處理的當前密鑰?
  3. http://www.developer.com/java/article.php/10922_3837316_2/Non-Blocking-IO-Made-Possible-in-Java.htm中,他們甚至建議在新線程中接受頻道。 我想有可能發生以下情況。

     key1 someClient1 acceptable key2 someClient2 not acceptable key3 someClient3 acceptable startThread1 startThread3 scheduler decides to give time to thread3 instead of thread1 thread3 -> socket.accept() <- actually accepts client1 thread1 -> socket.accept() <- actually accepts client3 

那么,您能否解釋一下選擇器如何與ServerSocketChannel和accept方法配對? 因為我不明白#accept接受客戶端的順序以及此命令與selectedKeys的關系。

  1. 我可以簡單地執行以下操作:

     int availableClients = 0; while (it.hasNext()) { SelectionKey selKey = (SelectionKey) it.next(); if (selKey.isAcceptable()) { ++availableClients; } it.remove(); } for (int i = 0; i < availableClients; ++i) { SocketChannel sc = server.accept(); doSomething(sc); } 

selKey.channel()返回一個ServerSocketChannel它與我們在ServerSocketChannel.open()開頭創建的通道完全相同嗎?

是。

更重要的問題:在大多數其他教程中selKey.channel(); 跳過步驟,他們只使用SocketChannel client = server.accept(); 例如: http//www.onjava.com/pub/a/onjava/2002/09/04/nio.html? page = 2 ,此處: http//www.developer.com/java/article。 php / 10922_3837316_2 / Non-Blocking-IO-Made-Possible-in-Java.htm那么,server.accept()如何知道我們處理的當前密鑰?

它沒有。 他們假設只有一個ServerSocketChannel 你的方式更好:它更通用。

http://www.developer.com/java/article.php/10922_3837316_2/Non-Blocking-IO-Made-Possible-in-Java.htm中,他們甚至建議在新線程中接受頻道。

我不知道為什么。 這是一個非阻塞的電話。 它會立即返回。 這個建議毫無意義。 忽略它。 這是六年前質量很差的教程,但十三年前還有更好的教程。 試試Oracle教程。 這個人的作者似乎根本不理解非阻塞模式。 為每個事件使用單獨的線程的建議是完全和完全荒謬的。 他也不明白如何使用OP_WRITE。 他對cancel()做出了錯誤的斷言。 我可以繼續 他曾經執行過這段代碼是值得懷疑的:他當然沒有以任何方式調查其行為。 如何編寫不可伸縮的NIO服務器。 相當壯舉。

我想有可能發生以下情況。

我甚至沒有看到為什么你會同時接受兩個線程,更不用說它們接受哪個客戶端的線程。 這是一個難以發明的難點。

那么,您能否解釋一下選擇器如何與ServerSocketChannel和accept方法配對? 因為我不明白#accept接受客戶端的順序以及此命令與selectedKeys的關系。

accept()方法返回積壓隊列中的下一個套接字,只要積壓隊列非空,就會觸發OP_ACCEPT。 它非常簡單,沒有神秘感。 該訂單根本不與“所選密鑰相關”。 所選密鑰是ServerSocketChannel密鑰。

編輯:看來你有一個重大的誤解。 考慮:

  1. 您為OP_ACCEPT創建並注冊ServerSocketChannel
  2. 兩個客戶端同時連接。
  3. 現在只有一個SelectionKey存在,因此在selected-key集中只有一個: ServerSocketChannel的那個。
  4. 然后,您在該鍵上處理isAcceptable()案例; 接受一個或兩個連接; OP_READ.注冊這些通道OP_READ.
  5. 現在有三個選擇鍵,並且在選擇鍵集中沒有,因為您清除了它。
  6. 兩個客戶端都發送一些數據。
  7. 現在,您已准備好在選定鍵組中讀取兩個選擇鍵。

好?

我可以簡單地執行以下操作:

當然,但為什么呢? 通過簡單的東西制造復雜的東西是沒有好處的。 這是第一種方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM