简体   繁体   English

使用NIO选择器从客户端向服务器发送自定义消息

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

So as the title suggests, I'm stuck on using selectors properly. 因此,正如标题所示,我坚持正确使用选择器。 The process I have in mind is that first when running this client as a thread, it will connect to the server, wait for a confirmation (CONNACK) and then proceed. 我想到的过程是,首先将此客户端作为线程运行时,它将连接到服务器,等待确认(CONNACK),然后继续。 So far so good, I am receiving the message SUCCESS! 到目前为止一切顺利,我收到的消息是SUCCESS! The server is set to read after accepting connection. 接受连接后,服务器设置为读取。

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();
     }
}

The problem however is when I call the publish method. 但是问题是当我调用publish方法时。 What I was planning to do was place the request in a synchronized queue. 我打算做的是将请求放置在同步队列中。 Then in the write method (when key.isWritable()) it checks the queue and if it finds anything, sends it to the server. 然后,在write方法中(当key.isWritable()时),它检查队列,如果发现任何内容,则将其发送到服务器。

PUBLISH 发布

 @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();
        }

The problem is that it never reaches key.isWritable() (hence, print "write key"). 问题在于它永远不会到达key.isWritable()(因此,打印“写密钥”)。 What could the problem be? 可能是什么问题?

When you have something to write, just write it, and check the return value. 当您有东西要写的时候,就写它,并检查返回值。 OP_WRITE should only be used in the case where a write() has just returned zero. 仅在write()返回零的情况下才应使用OP_WRITE。 There are plenty of answers about this here, many of them by me. 这里有很多答案,其中很多是我的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM