简体   繁体   中英

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. So far so good, I am receiving the message 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. 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.

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"). 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. There are plenty of answers about this here, many of them by me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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