NIO: Client thinks it is connected, Server hasn't accept()ed yet

Hi all,

I’m posting this in Newless Clubies, as I’m obviously making a trival mistake.

I have a non-blocking ServerSocketChannel that binds to local_ip@4455, do NOT register it for OP_ACCEPT. Then I create a SocketChannel, that connects to local_ip@4455, register for OP_READ and OP_WRITE. The client gets OP_WRITE and even manages to send bytes to the server (socketChannel.write() returns >0). The server does not receive any bytes (as it didn’t even register for OP_ACCEPT, so doesn’t know about the client).

So the client thinks it is connect to the server, yet the server did never accept() any socket.

So, what on earth am I missing?

Thank you!

Program output:

launching server.. done
launching client... done
[NOTI] ClientLogger.clientConnected(Client[192.168.123.150:1532 -> 192.168.123.150:4555])
client writes 4 bytes
client writes 2 bytes
[NOTI] ClientLogger.clientSentPacket(Client[192.168.123.150:1532 -> 192.168.123.150:4555])

Self-contained source-code:

System.out.println("local_ip = " + InetAddress.getLocalHost());

         // server
         final Selector serverSelector = Selector.open();
         ServerSocketChannel ssc = ServerSocketChannel.open();
         ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 4555));
         ssc.configureBlocking(false);
         ssc.register(serverSelector, SelectionKey.OP_ACCEPT);

         // client
         final Selector clientSelector = Selector.open();
         SocketChannel sc = SocketChannel.open();
         sc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
         sc.socket().connect(new InetSocketAddress(InetAddress.getLocalHost(), 4555));
         sc.configureBlocking(false);
         sc.register(clientSelector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

         Runnable serverLoop = new Runnable()
         {
            public void run()
            {
               try
               {
                  while (true)
                  {
                     serverSelector.select();
                     Iterator<SelectionKey> selectedKeys = serverSelector.selectedKeys().iterator();

                     while (selectedKeys.hasNext())
                     {
                        SelectionKey key = selectedKeys.next();
                        selectedKeys.remove();

                        if (key.isAcceptable())
                           System.out.println("server: socket available, but not accepting it!");
                     }

                     Thread.sleep(1000);
                  }
               }
               catch (Exception exc)
               {
                  exc.printStackTrace();
               }
            }
         };

         Runnable clientLoop = new Runnable()
         {
            public void run()
            {
               try
               {
                  while (true)
                  {
                     clientSelector.select();
                     Iterator<SelectionKey> selectedKeys = clientSelector.selectedKeys().iterator();

                     while (selectedKeys.hasNext())
                     {
                        SelectionKey key = selectedKeys.next();
                        selectedKeys.remove();

                        if (key.isReadable())
                           System.out.println("client: can read bytes");

                        if (key.isWritable())
                        {
                           System.out.println("client: can write bytes");
                           ByteBuffer bb = ByteBuffer.wrap(new byte[64]);
                           System.out.println("  client writes " + ((SocketChannel) key.channel()).write(bb) + " bytes");
                        }
                     }

                     Thread.sleep(1000);
                  }
               }
               catch (Exception exc)
               {
                  exc.printStackTrace();
               }
            }
         };

         new Thread(serverLoop).start();

         try
         {
            Thread.sleep(1000);
         }
         catch (Exception exc)
         {
            //
         }

         new Thread(clientLoop).start();

Output:

local_ip = riven/192.168.123.150

server: socket available, but not accepting it!
client: can write bytes
  client writes 64 bytes

server: socket available, but not accepting it!
client: can write bytes
  client writes 64 bytes

etc etc etc

Java 1.5.0_06 (Sun, client-vm)
Windows XP

Could anybody at least run this code and post the results?

Thank you very much!

at first glance: what do you mean it dosen’t register for accept? I see


ssc.register(serverSelector, SelectionKey.OP_ACCEPT);

in 10th line from your code

Yes, I posted the 2nd version of my test-case. Whether or not i register makes no diff, same output. :-\

you helped me out so I’ll at least run the code shortly… been busy lately

Really strange… when you bind server to the port it can automaticly receive data. Maybe that’s normal behaviour? Server dosen’t even need to start, just binds the port and it can receive data. I commented his thread … works. Commented bind method… dosen’t work. I guess when something binds port it makes it his and can receive everything.

Thank you for running my code,

appearantly, this is a rarely encountered (yet serious) bug in NIO.

Do you have link to bug report?

I already submitted the bug, will have to wait about three weeks before they respond, according to the website… :wink:

yeah… I meant link to description of bug, not bug reporting system itself. Of course you’ll fill in bug report as it’s your discovery :slight_smile:
Post it when it gets there… I’m courius about this.