簡體   English   中英

使用NIO選擇器從客戶端向服務器發送自定義消息

[英]Sending a custom message to a server from client using NIO selectors

因此,正如標題所示,我堅持正確使用選擇器。 我想到的過程是,首先將此客戶端作為線程運行時,它將連接到服務器,等待確認(CONNACK),然后繼續。 到目前為止一切順利,我收到的消息是SUCCESS! 接受連接后,服務器設置為讀取。

while (iterator.hasNext()) {
     final SelectionKey key = (SelectionKey) iterator.next();

     iterator.remove();

     try (SocketChannel keySocketChannel = (SocketChannel) key.channel()) {

     //attempt connection
     if (key.isConnectable()) {
             System.out.print("Connecting");

             if (keySocketChannel.isConnectionPending()) {
                 keySocketChannel.finishConnect();
             }

             while (keySocketChannel.read(buffer) != -1) {
                 buffer.flip();

                 charBuffer = decoder.decode(buffer);
                 System.out.print(".");

                 if (buffer.hasRemaining()) {
                        buffer.compact();
                 } else {
                        buffer.clear();
                 }
                 if (charBuffer.toString().equals(MessageType.CONNACK.getName())) {
                        System.out.println("SUCCESS!");

                        //At this point, it makes sense that the next operation
                        //is a write.
                        key.interestOps(SelectionKey.OP_WRITE);
                        break;
                  }
                  try {
                        Thread.sleep(500);
                  } catch (InterruptedException e) {
                  }
              }
              System.out.println("SUCCESS!");
              key.interestOps(SelectionKey.OP_WRITE);
     } else if (key.isConnectable())  {
              System.out.println("connectable");
     } else if (key.isWritable()) {
              System.out.println("write key");
              write(key, socketChannel);
     } else if (key.isReadable()) {
              System.out.println("read key");
     }
              System.out.println("oops");
     } catch (IOException e) {
              e.printStackTrace();
     }
}

但是問題是當我調用publish方法時。 我打算做的是將請求放置在同步隊列中。 然后,在write方法中(當key.isWritable()時),它檢查隊列,如果發現任何內容,則將其發送到服務器。

發布

 @Override
        public void publish(String message) {
            //create publish request
            final Request request = new Request(this.topic, message, MessageType.PUBLISH);

            System.out.println("Adding request to queue..");
            synchronized (this.dataQueue) {
                dataQueue.add(request);
            }
            this.selector.wakeup();
        }

問題在於它永遠不會到達key.isWritable()(因此,打印“寫密鑰”)。 可能是什么問題?

當您有東西要寫的時候,就寫它,並檢查返回值。 僅在write()返回零的情況下才應使用OP_WRITE。 這里有很多答案,其中很多是我的。

暫無
暫無

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

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