Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4737146

(so) key.isConnectable() true even after connection complete

XMLWordPrintable

    • mantis
    • x86
    • windows_2000
    • Verified



      Name: gm110360 Date: 08/26/2002


      FULL PRODUCT VERSION :
      j2sdk-1_4_1-rc-windows-i586.exe

      Java 2 Enterprise Edition version 1.3.1, build 1.3.1-b17

      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]

      A DESCRIPTION OF THE PROBLEM :
      I have a NIO Client and Server using non-bloacking mode.
      When client connects to the server the selector respond
      back saying
      Connecting ....
      Processing selecion key.isConnectable()=true key.isReadable
      ()=false

      which is correct. Then i wait till finishConnect() and
      write something on the stream to send to server. Server
      respond back.

      This time when the selector returns back on the client side
      it still show me isConnectable() = true ??

      Processing selecion key.isConnectable()=true key.isReadable
      ()=true

      And the while loop
      while ( selector.select() > 0 ) {
      keeps on executing and behave like while(true).






      REGRESSION. Last worked in version 1.4

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Please find the source attached.
      1.Execute the Server
      2. Execute the client


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The client will keep on recursively sending data to server
      as the loop
      while ( selector.select() > 0 ) {
      behaves as if while(true)
      this happens on the client side


      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      This is a problem of selector reporting.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      ######################### CLIENT CODE ##################################
      import java.nio.*;
      import java.nio.charset.*;
      import javax.swing.*;
      import java.awt.*;
      import java.awt.event.*;

      class NIOClient {
      public static void main(String[] args) {
      System.out.println("Connecting ....");
      connect();
      System.out.println("Connected.");
      }

      public static void connect() {
      try{
      java.net.InetAddress lh =
      java.net.InetAddress.getLocalHost();
      java.net.InetSocketAddress socketAddress = new
      java.net.InetSocketAddress(lh, 5555);
      java.nio.charset.Charset charset =
      java.nio.charset.Charset.forName("us-ascii");
      java.nio.charset.CharsetEncoder encoder =
      charset.newEncoder();
      java.nio.charset.CharsetDecoder decoder =
      charset.newDecoder();

      //allocate buffers
      ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
      CharBuffer charBuffer = CharBuffer.allocate(1024);

      java.nio.channels.SocketChannel channel =
      java.nio.channels.SocketChannel.open();

      // make the channel as non-blocking
      channel.configureBlocking(false);

      // for a non-blocking io it should written immediately
      channel.connect(socketAddress);

      //get the selector
      //java.nio.channels.Selector selector =
      java.nio.channels.Selector.open();
      java.nio.channels.Selector selector =
      java.nio.channels.spi.SelectorProvider.provider().openSelector();

      //register the channel
      channel.register(selector,
      java.nio.channels.SelectionKey.OP_CONNECT |
      java.nio.channels.SelectionKey.OP_READ );

      while ( selector.select() > 0 ) {
      // get the set of ready object
      java.util.Set keys = selector.selectedKeys();

      java.util.Iterator readyItor = keys.iterator();

      //walk through the set
      while ( readyItor.hasNext() ) {

      // get the ket from the set
      java.nio.channels.SelectionKey key =
      (java.nio.channels.SelectionKey)readyItor.next();

      //remove the current entry
      readyItor.remove();

      // get the channel
      java.nio.channels.SocketChannel
      keyChannel = (java.nio.channels.SocketChannel)key.channel();

      System.out.println("Processing selecion
      key.isConnectable()=" + key.isConnectable() + " key.isReadable()=" +
      key.isReadable() );

      if ( key.isConnectable() ) {

      //Finish connection
      if (
      keyChannel.isConnectionPending() ) {
      keyChannel.finishConnect
      ();
      }

      String request = "Hello, how
      are you ?\n";
      keyChannel.write(encoder.encode
      ( CharBuffer.wrap(request) ));

      //clear the buffers
      buffer.clear();
      charBuffer.clear();
      } else if( key.isReadable() ) {

      ByteBuffer byteBuffer =
      ByteBuffer.allocate(1024);
      int nbytes = keyChannel.read(
      byteBuffer );
      byteBuffer.flip();
      String result = decode(
      byteBuffer );
      System.out.println(result);

      //clear the buffers
      buffer.clear();
      charBuffer.clear();
      } else {
      System.out.println("Ooops");
      }

      }

      }

      } catch ( java.lang.IllegalArgumentException iae ) {
      iae.printStackTrace();
      } catch ( java.nio.channels.NotYetConnectedException nyce ) {
      nyce.printStackTrace();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }

      public static String decode( ByteBuffer byteBuffer ) throws
      java.nio.charset.CharacterCodingException{
      Charset charset = Charset.forName("us-ascii");
      CharsetDecoder decoder = charset.newDecoder();
      CharBuffer charBuffer = decoder.decode( byteBuffer );
      String result = charBuffer.toString();
      return result;
      }

      }





      ######################### SERVER CODE ##################################


      import java.io.*;
      import java.nio.*;
      import java.nio.channels.*;
      import java.nio.charset.*;

      class NIOServer implements Runnable {
      int port = 5555;
      static final int BUFSIZE = 30;
      java.nio.channels.Selector selector = null;
      java.nio.channels.ServerSocketChannel selectableChannel = null;
      java.util.Vector list = new java.util.Vector();
      int keysAdded = 0;

      static String QUIT_SERVER = "quit";
      static String SHUTDOWN = "shutdown";

      public NIOServer() {
      }

      public NIOServer(int port) {
      this.port = port;
      }

      public void initialize () throws java.io.IOException {
      this.selector = java.nio.channels.spi.SelectorProvider.provider
      ().openSelector();
      this.selectableChannel =
      java.nio.channels.ServerSocketChannel.open();
      this.selectableChannel.configureBlocking(false);

      java.net.InetAddress lh = java.net.InetAddress.getLocalHost();
      java.net.InetSocketAddress isa = new java.net.InetSocketAddress
      (lh, this.port);

      this.selectableChannel.socket().bind(isa);
      }

      protected void finalize() throws java.io.IOException {
      this.selectableChannel.close();
      this.selector.close();
      }

      public void log(String msg) {
      System.out.println(msg);
      }

      public void acceptConnections() {
      try {
      //register the channel
      java.nio.channels.SelectionKey acceptKey =
      this.selectableChannel.register(this.selector,
      java.nio.channels.SelectionKey.OP_ACCEPT);

      this.log("Acceptor loop...");

      // walk through the keys
      while ( (this.keysAdded = acceptKey.selector().select
      ()) > 0 ) {
      this.log("Selector returned " + this.keysAdded
      + " ready for IO operation.");

      //get the ready set of objects
      java.util.Set readyKeys = selector.selectedKeys
      ();
      java.util.Iterator i = readyKeys.iterator();

      while( i.hasNext() ) {
      java.nio.channels.SelectionKey key =
      (java.nio.channels.SelectionKey)i.next();
      i.remove();

      if ( key.isAcceptable() ) {
      // get the channel accociated
      with this key

      java.nio.channels.ServerSocketChannel nextReady =
      (java.nio.channels.ServerSocketChannel)key.channel();

      this.log("Processing selecion
      key read=" + key.isReadable() + " write=" + key.isWritable() + " accept=" +
      key.isAcceptable() );

      java.nio.channels.SocketChannel
      channel = nextReady.accept();
      channel.configureBlocking
      (false);

      java.nio.channels.SelectionKey
      readyKey =
      channel.register
      (this.selector, java.nio.channels.SelectionKey.OP_READ);
      ChannelCallback cc = new
      ChannelCallback(channel);
      readyKey.attach(cc);

      //add to the list
      this.list.add(cc);
      } else if ( key.isReadable() ) {
      // get the channel accociated
      with this key

      java.nio.channels.SelectableChannel nextReady =
      (java.nio.channels.SelectableChannel)key.channel();

      this.log("Processing selecion
      key read=" + key.isReadable() + " write=" + key.isWritable() + " accept=" +
      key.isAcceptable() );
      ChannelCallback cc =
      (ChannelCallback)key.attachment();
      this.readMessage(cc);
      }
      }
      }
      } catch (Exception e) {
      }

      this.log("End of acceptor loop.");
      }

      public void writeMessage(java.nio.channels.SocketChannel channel,
      String message) throws java.io.IOException {
      ByteBuffer buf = ByteBuffer.wrap( message.getBytes() );
      int nbytes = channel.write(buf);
      this.log("Wrote " + nbytes + " to channel.");
      }

      public String decode( ByteBuffer byteBuffer ) throws
      java.nio.charset.CharacterCodingException{
      Charset charset = Charset.forName("us-ascii");
      CharsetDecoder decoder = charset.newDecoder();
      CharBuffer charBuffer = decoder.decode( byteBuffer );
      String result = charBuffer.toString();
      return result;
      }

      public void readMessage( ChannelCallback callback ) throws
      java.lang.InterruptedException {
      ByteBuffer byteBuffer = ByteBuffer.allocate(BUFSIZE);
      try {
      int nbytes = callback.getChannel().read( byteBuffer );

      byteBuffer.flip();
      String result = this.decode( byteBuffer );

      if (result.indexOf("quit") >= 0 ) {
      callback.getChannel().close();
      } else if ( result.indexOf("shutdown") >= 0 ){
      callback.getChannel().close();
      throw new java.lang.InterruptedException();

      } else {
      callback.append( result );
      if ( result.indexOf("\n") >= 0 ) {
      //if we are done with the line then we
      execute the callback
      callback.execute();
      }
      }
      } catch (java.io.IOException ioe) {
      //System.out.println("Removing the channel from the
      list.");
      this.list.remove(callback);
      }
      }


      public static void main(String[] args)
      {
      System.out.println("Hello World!");
      NIOServer nioServer = new NIOServer();
      try {
      nioServer.initialize();
      } catch(Exception e) {
      e.printStackTrace();
      }

      Thread t = new Thread(nioServer);
      t.start();

      try {
      nioServer.acceptConnections();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }

      public void run() {
      while (true) {
      System.out.println(list.size());
      java.util.Enumeration enum = list.elements();
      while( enum.hasMoreElements() ) {
      ChannelCallback cc = (ChannelCallback)
      (enum.nextElement());
      try {
      writeMessage(cc.getChannel(), "I am
      fine thanx.");
      } catch (Exception e){
      e.printStackTrace();
      list.remove(cc);
      }
      }

      try {
      Thread.sleep(10000);
      } catch (Exception e){}
      }
      }

      class ChannelCallback {
      private SocketChannel channel;
      private StringBuffer buffer;

      public ChannelCallback( java.nio.channels.SocketChannel
      channel ) {
      this.channel = channel;
      buffer = new StringBuffer();
      }

      public void execute() throws IOException {
      System.out.println(this.buffer.toString());
      writeMessage( this.channel, this.buffer.toString() );
      buffer = new StringBuffer();
      }

      public SocketChannel getChannel() {
      return this.channel;
      }

      public void append(String values) {
      this.buffer.append(values);
      }
      };
      }








      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      If you execute this with the previous version
      java version "1.4.0_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build
      1.4.0_01-b03)
      Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)

      The same sample code works fine.

      Release Regression From : 1.4.0_01
      The above release value was the last known release where this
      bug was known to work. Since then there has been a regression.

      (Review ID: 163533)
      ======================================================================

            mmcclosksunw Michael Mccloskey (Inactive)
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: