NIO: multiple selectors

Hi,
How to implement nb server with multiples selectors? I have 3 selectors and 3 corresponding threads. Every selector serve for one type of operation OP_ACCEPT, OP_READ and OP_WRITE. When I receive a new connection and try to register a new channel with other selector the operation blocks on Channel.register(). It works only with the same selector that accepted this connection.
                    if ( key.isAcceptable() ) {
                        // accepting incoming socket connection
                        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                             SocketChannel ch = ssc.accept();
                             // registering client
                             ch.configureBlocking( false );
                             ch.socket().setReceiveBufferSize( RECEIVE_BUFFER_SIZE );
                             ch.socket().setSendBufferSize( SEND_BUFFER_SIZE );
                             ch.register( readSelector, SelectionKey.OP_READ );
                        }Is it possible to use various selectors?

Dunno what you've done exactly but Selector.select() does three levels of synchronization which are described in the Javadoc, and SelectableChannel.register() also needs to synchronize on of of those items, i.e. the registered key set.
A separate reading thread can only help if there are multiple processors and the different threads are executing in different processors. I'm dubious about the strategy of separating reading from writing specifically. If I was going to use multiple selectors I would allocate channels to them arbitrarily rather than on the basis of OP_READ/OP_WRITE.

Similar Messages

  • Changing properties of multiple selectors?

    Hello everyone
    In the section titled Specify default font properties on this page, What is CSS? | Adobe Dreamweaver CC tutorials,
    instructions read as follows:
         Click html, button, input, select, textarea in the Selectors list.
    Does this imply that the properties of these selectors can be modified simultaneously? The Properties Pane of CSS Designer shows no content once I select multiple selectors in the Selectors list.
    Also, the button, input and select selectors do not display in the Selectors list.
    Red

    Does this imply that the properties of these selectors can be modified simultaneously?
    Correct.

  • NIO + multiple packets

    How does a web server take multiple packets from a client and make one large request out of it?
    I have a NIO server which until now has always assumed "requests" were being sent with one packet. Thus, I built my code to always assume each request = one read from the selection key = one action I take.
    For example, if I sent "hello there server" as a command, the server would parse "hello there server" and I would execute some return logic based on that request.
    Now I have very long requests that are being received as multiple packets. For example "hello there server blah blah blah" is being recieved as "hello there server" (packet 1) and then "blah blah blah" (packet 2). (just humor me, it happens with longer requests than that ;-)
    I assume this happens a lot with http servers - So how do I put multiple packets "together" in NIO? Would I store the contents of each packet into memory until the last packet of a request arrives, then parse the request? Thanks!

    If your packets are character strings you can use the fact that CharBuffer implements CharSequence and can be used much like a StringBuffer. See the code example below. Otherwise you could just keep a ByteBuffer and copy the data from using put.
    Here's the example for strings, the rest of this application is in my post Taming the NIO Circus
         // reception support
         // receive a string
         private void doRead()
              String dat;
              while(null != (dat = readLine()))client.fromRemote(dat); // send it back to the client
              if(atEof)close();
         private String readLine()
              String s = null;
              fill();
              int len = recvString.length();
              int n = firstNL();
              if(n == -1)
                   if(atEof && 0 < len)
                        s = recvString.substring(0);
                        n = len;
              else
                   s = recvString.substring(0,n);
                   if(len > n+1 && recvString.charAt(n)=='\r' && recvString.charAt(n+1)=='\n')n+=2;
                   else n++;
              if(n > 0)
                   recvString.delete(0,n);
                   recvScanned = 0;
              return s;
         public boolean fill()
              CharBuffer buf;
              int len=0;
              recvBuffer.clear();
              try{len = sch.read(recvBuffer);}
              catch(Exception e){e.printStackTrace();atEof=true;}
              recvBuffer.flip();
              if(len > 0)
                   dout(1,"read "+len+" bytes");
                   try
                        buf = decoder.decode(recvBuffer);
                        dout(0,"received="+buf);
                        recvString.append(buf);
                   catch(Exception e){e.printStackTrace();atEof = true;}
              else if(len < 0)atEof = true;
              return atEof;
         // scan recvString for first new line
         private int firstNL()
              while(recvScanned < recvString.length())
                   char ch = recvString.charAt(recvScanned);
                   if(ch == '\r' || ch == '\n')return recvScanned;
                   recvScanned++;
              return -1;     // no cr or lf
         }

  • Detect loss of socket connection using java.nio.channels.Selector

    I'm using the nio package to write a "proxy" type application, so I have a ServerSocketChannel listening for incoming connections from a client and then create a SocketChannel to connect to a server. Both SocketChannels are registered to the same Selector for OP_READ requests.
    All works fine, until either the client or server drops the connection. How can I detect this has happened, so my proxy app can drop the other end of the connection ?
    The Selector.select() method is not triggered by this event. I have tried using Selector.select(timeout) and then checking the status of each channel, but they still show isConnected()=true.
    Thanks,
    Phil Blake

    Please don't cross post.
    http://forum.java.sun.com/thread.jsp?thread=184411&forum=4&message=587874

  • Java nio Pipe - Selector ptoblem

    I try to use a Pipe with a non-blocking selector,
    but the selector never selects the channel ...
    -- I do this ---
    Selector selector = SelectorProvider.provider().openSelector();
    Pipe pipe = Pipe.open();
    Pipe.SourceChannel cout = pipe.source();
    cout.configureBlocking( false );
    cout.register( selector, SelectionKey.OP_READ );
    --- and in a nother thread i do this on the Pipe( same pipe ) ---
    ByteBuffer buffin = ByteBuffer.wrap( "Testing".getBytes() );
    Pipe.SinkChannel cin = pipe.sink();
    cin.write( buffin );
    if I read from the source I can read the data but the selector never selects it ??
    /Mikael

    Interesting problem.
    This code seems to work for me:
        final Pipe pipe = Pipe.open();
        final Pipe.SourceChannel cout = pipe.source();
        final Selector s = Selector.open();
        cout.configureBlocking(false);
        cout.register(s, SelectionKey.OP_READ);
        Thread thread = new Thread(new Runnable() {
          public void run() {
            try {
            ByteBuffer buf = ByteBuffer.wrap("Testing".getBytes());
            Pipe.SinkChannel cin = pipe.sink();
            cin.write(buf);
            System.out.println("wrote");
            } catch (Exception e) {
              throw new RuntimeException(e.toString());
       thread.start();
       s.select();
       Iterator i = s.selectedKeys().iterator();
       while (i.hasNext()) {
         SelectionKey key = (SelectionKey)i.next();
         Pipe.SourceChannel out = (Pipe.SourceChannel)key.channel();
         ByteBuffer dbuf = ByteBuffer.allocate(1024);
         int read = out.read(dbuf);
         dbuf.flip();
         byte[] bbuf = new byte[read];
         dbuf.get(bbuf);
         System.out.println(new String(bbuf));
       }Is that different from your code??????
    I tested this on a Windows 2K desktop with JDK 1.4.1_01 from Sun.

  • Case Structure - multiple selectors, single exit

    I tried searching for an anwser to my question but I could not find one.
    I'm creating an interface for my graduation project (using LabVIEW 7.1) and I will be using several subpanel's, at this point I'm trying to create a selection method. During the design of the interface the users gave preference to buttons for switching between the different subpanels (there is a total of 4 buttons). And a subpanel is chosen based on a numeric value (I have taken the code from the viewer.vi example).
    Now I'm trying to work out some sort of case structure starting from the 4 buttons and resulting in a single numeric value. The idea being that when button 1 is pressed, subpanel 1 is active and every other panel is not. So far I haven't found a working one, especially because of the single numeric value I want to have.
    If the anwser is somewhere on this board then you have my apologies and I would appreciate a link to it.
    If something is not clear: feel free to ask questions.

    That's why a radio button control is better. It automatically allows only one button to be active. Clicking a new one will turn the others off.
    Try it! Just place any number of booleans (any style) inside the radio button control. The output will be a single number. If you wire it to a case structure, you'll get the control label for each as case name.
    (you can also allow or disallow "no selection", etc.)
    LabVIEW Champion . Do more with less code and in less time .
    Attachments:
    RadioButtons.vi ‏10 KB

  • NIO Selector.select() enters a 100% CPU infinite loop on interruption

    This issue is only reproducible in Windows.
    When a thread is calling Selector.select() and the other thread interrupts the selector thread, Selector.select() enters an infinite loop taking up CPU time.  All other JDKs I've tried including IBM 1.5 / 1.6, SUN 1.5 / 1.6 simply returned 0 when its interrupted.  I think JRockit needs to behave similarly, without 100% CPU consumption.  Here's the test code:
    import java.nio.channels.Selector;
    public class Main {
          public static void main(String[] args) throws Exception {
                  final Thread mainThread = Thread.currentThread();
                  final Selector s = Selector.open();
                  new Thread() {
                          @Override
                          public void run() {
                                      try {
                                                Thread.sleep(1000);
                                      } catch (InterruptedException e) {
                                                // Ignore.
                                      System.out.println("interrupt()");
                                      mainThread.interrupt();
                  }.start();
                  System.out.println("select()");
                  s.select(5000);
                  System.out.println("success");
                  s.close();
    Expected result:
            select()
            interrupt()
            success
    Actual result:
            select()
            interrupt()
            &lt;stuck with 100% CPU consumption&gt;
    Version:
            JRMC-3.0.3-1.5.0 - build R27.6.0-50_o-100423-1.5.0_15-20080626-2105-windows-ia32, compiled mode
            JRMC-3.0.3-1.6.0 - build R27.6.0-50_o-100423-1.6.0_05-20080626-2105-windows-ia32, compiled mode

    Hi,
    This looks like a bug. Please open a support ticket and request a patch if you need a fix asap. If you can wait we will fix this in an upcoming release. Thank you for your help

  • Random TCP connections created in Selector.open (in NIO)

    I'm currenlty running a production app which has several independently running application server classes going at any given time. Each of these uses one Selector to provide support for asynchronous I/O operations. Lately I noticed that when bouncing one of these servers I'd have problems bringing it back up because of sequential "ghost listeners" and "ghost connections" colliding with the ports I was interested in.
    So, I got out a local port-scanner and did some digging. To my chagrin I discovered that every time I made a call to Selector.open() a new TCP connection was made from my application to my application on an internal port. In Java 1.4.2_02 this occured on the "primary" network adapter. In Java 1.5 this occured on the loopback adapter. Unfortunately for me neither is acceptable because my app regularly binds and unbinds for listening on varying adapters including the wildcard adapter (0.0.0.0) and I can't have my own process colliding with itself trying to listen to ports.
    Okay, so then I did some forum searching with the help of a couple co-workers. It turns out these connections are "normal" and related to something called the "wakupPipe", or "wakup pipe". Also, this seems somewhat related to something we call the "runaway select event" in-house (where Selector.select(x) returns 0 before the timeout is up over and over again, which we've long since worked around to support Java 1.4.2_02).
    This problem occurs on windows 2000 and windows server 2003. I've attached a code-snippet below that will duplicate the problem (and flood a system with extraneous TCP connections if left running long enough).
    My questions are:
    1) Why in the world did this wakup pipe have to be implemented as a TCP connection (rather than in-memory)?
    2) Why is this not documented anywhere in the Java API's, or am I missing the documentation of it?
    3) Is there some way to control the behaviour of this "wakup pipe"? (ie: make it be in-memory only, a file, or specify port-range, IP etc...)
    4) Isn't it dangerous to create a library based on undocumented and randomly allocated TCP connections that can't be controlled via configuration?
    import java.nio.channels.Selector;
    import java.util.ArrayList;
    public class NIOSelectorOpenExample implements Runnable {
        protected boolean shouldRun = true;
        public void shutdown() { shouldRun = false; }
        public void run()
          try {
            ArrayList selectors = new ArrayList();
            while( shouldRun )
                selectors.add( Selector.open() );
                Thread.currentThread().sleep(500);
          } catch (Exception ex) {
              ex.printStackTrace();
    }Basically on #4 I want to know why/if running this code wouldn't be a major problem on any system that opens and closes ports for listening regularly. (And yes, aside from the fact that it doesn't explicitly clean up the selectors before exiting.)

    Hmmm ...
    We had an issue in production where one
    of the ServerSocketChannels failed to bind because it
    collided with the wakeup pipe range. Of course, this
    was on Java 1.4.2_02 which binds on the primary
    adapter for the system and not the loopback adapter.This seems back to front. By default Java binds to INADDR_ANY which is all the interfaces, which is why you got the collision on the loopback port which was already there. If it bound the socket to a specific non-loopback NIC there would be no collision with any loopback port, they are different number spaces.
    Are you able to create all the ServerSockets before any of the Selectors?
    or, if your hosts aren't multihomed, is it practical for the application to bind its ServerSockets to the primary NIC (i.e. the non-loopback)?
    Yes, we can repeatedly try to bind on a port and
    d perform other work-arounds, but why should we have
    to? How could we have expected this behavior? (It
    may be a Windows limitation that caused Sun to choose
    their implementation method, but non-Java TCP apps on
    windows don't have these problems...)Agreed, but then again non-Java TCP apps don't try to implement select() for arbitrary numbers of sockets to agree with *nix platforms, they can generally live with <= 64.
    Note: The problem appears exacerbated from having the
    listen ports of these wakeup pipe connections stay
    open for long periods of time (rather than closing as
    soon as the pipe is established). Would this help? There would still be the connected port with the same number & this might inhibit a new listening port with that number. Haven't tried this myself.
    Well, considering the behavior changed between
    1.4.2_02 and 1.5 it can't be all that inaccessible a
    fix. Perhaps using an extra TCP connection was
    necessary in some cases, but obviously binding to
    ("127.0.0.1", 0) isn't the only choice since it has
    changed recently and those values could easily be
    made configurable (given access to the code
    involved).It changed from binding to 0, i.e. INADDR_ANY, in 1.4 to binding to 127.0.0.1 in 1.5, probably in an effort to vacate the port space for the physical NICs.
    Given access to the code involved you can change anything. In the SCSL code it is sun.nio.ch.WIndowsSelectorImpl.java in src/windows/classes.
    Actually, I'm also wondering if a single
    (known-default/configurable) listen port wouldn't be
    adequate for all of these wakeup pipe TCP
    connections. Me too.
    Regards
    EJP

  • NIO Socket implementation - delay between select and get data from socket

    Hi all,
    I have implemented a internal CallAPI for RPC over a socket connection. It works fine but if there are more than five clients and some load I have the phenomena that the READ selector returns a SelectorKey but I did not get any data from the socket.
    My implementation is based on NIO has following components:
    + Accept-Thread
    Thread handles new clients.
    + Read-Thread
    Thread handles the data from the socket for the registered client. Each request is handled in an own Process-Thread. A Thread-Pool implementation is used for processing.
    + Process-Thread
    The Process-Thread reads the data from the socket and starts the processing of the logical request.
    In my tests I get the notification of data at the socket. The Process-Thread want to read the data for the socket, but no data are available. In some situations if have to read about 20 times and more to get the data. Between each read attempt I have inserted a sleep in the Process-Thread if no data was available. This have improved the problem, but it already exists. I tested the problem with several systems and jvm's but it seams that it is independent from the system.
    What can I to do improve the situation?
    I already include the read implementation from the grizzly-Framework. But it doesn't improve the situation.
    Socket - Init
         protected void openSocket( String host, int port ) throws IOException
              serverChannel = ServerSocketChannel.open();
              serverChannel.configureBlocking( false );
              serverSocket = serverChannel.socket();
              serverSocket.setReuseAddress( true );
              this.serverhost = host;
              this.serverport = port;
              this.srvAcceptSelector = Selector.open();
              this.srvReadSelector = Selector.open();
              InetSocketAddress isa = null;
              if ( serverhost != null )
                   isa = new InetSocketAddress( this.serverhost, this.serverport );
              else
                   isa = new InetSocketAddress( this.serverport );
              serverSocket.bind( isa, 50 );
              serverChannel.register( this.srvAcceptSelector, SelectionKey.OP_ACCEPT );
         }New Client � Init
         // New Client
         if ( key.isAcceptable())
              keyCountConnect++;
              ServerSocketChannel actChannel =
                   (ServerSocketChannel) key.channel();
              // Socket akteptieren
              SocketChannel actSocket = actChannel.accept();
              if ( actSocket != null )
                   actSocket.finishConnect();
                   actSocket.configureBlocking( false );
                   actSocket.socket().setTcpNoDelay( true );
                   this.registerSocketList.add( actSocket );
                   this.srvReadSelector.wakeup();
         }Read Data from Socket
        protected int readDatafromSocket( ByteArrayOutputStream socketdata )
             throws IOException
             int readedChars = 0;
            int count = -1;
            Selector readSelector = null;
            SelectionKey tmpKey = null;
            if ( sc.isOpen())
                  ByteBuffer inputbuffer = null;
                 try
                      inputbuffer = bufferpool.getBuffer();
                      while (( count = sc.read( inputbuffer )) > 0 )
                           readedChars += count;
                          inputbuffer.flip();
                           byte[] tmparray=new byte[inputbuffer.remaining()];
                           inputbuffer.get( tmparray );
                           socketdata.write( tmparray );
                          inputbuffer.clear();
                      if ( count < 0 )
                           this.closeSocket();
                           if( readedChars == 0 )
                                readedChars = -1;
                           if ( log.isDebug())
                                  log.debug( "Socket is closed! " );
                      else if ( readedChars == 0 )
                           if ( log.isDebug())
                                  log.debug( "Reread with TmpSelector" );
                           // Glassfish/Grizzly-Implementation
                         readSelector = SelectorFactory.getSelector();
                         if ( readSelector == null )
                              return 0;
                          count = 1;
                          tmpKey = this.sc.register( readSelector, SelectionKey.OP_READ );
                         tmpKey.interestOps(
                              tmpKey.interestOps() | SelectionKey.OP_READ );
                         int code = readSelector.select( 500 );
                         tmpKey.interestOps(
                             tmpKey.interestOps() & ( ~SelectionKey.OP_READ ));
                         if ( code == 0 )
                             return 0;
                             // Return on the main Selector and try again.
                           while (( count = sc.read( inputbuffer )) > 0 )
                                readedChars += count;
                               inputbuffer.flip();
                                byte[] tmparray=new byte[inputbuffer.remaining()];
                                inputbuffer.get( tmparray );
                                socketdata.write( tmparray );
                               inputbuffer.clear();
                           if ( count < 0 )
                                this.closeSocket();
                                if( readedChars == 0 )
                                     readedChars =-1;
                           else if ( count == 0 )
                                  // No data
                 finally
                      if ( inputbuffer != null )
                           bufferpool.releaseBuffer( inputbuffer );
                           inputbuffer = null;
                      // Glassfish-Implementierung
                    if ( tmpKey != null )
                        tmpKey.cancel();
                    if ( readSelector != null)
                        // Bug 6403933
                         try
                            readSelector.selectNow();
                         catch (IOException ex)
                        SelectorFactory.returnSelector( readSelector );
            return readedChars;
        }Thanks for your time.

    I've commented on that blog before. It is rubbish:
    - what does 'overloading the main Selector' actually mean? if anything?
    - 'Although this not clearly stated inside the NIO API documentation': The API documentation doesn't say anything about which Selector you should register channels with. Why would it? Register it with any Selector you like ...
    - 'the cost of maintaining multiple Selectors can reduce scalability instead of improving it' Exactly. So what is the point again?
    - 'wrapping a ByteBuffer inside a ByteBufferInputStream:' Code is rubbish and redundant. java.nio.channels.Channels has methods for this.
    There is no a priori advantage to using multiple Selectors and threads unless you have multiple CPUs. And even then not much, as non-blocking reads and writes don't consume significant amounts of CPU. It's the processing of the data once you've got it that takes the CPU, and that should be done in a separate thread.
    So I would re-evaluate your strategy. I suspect you're getting the channel registered with more than one Selector at a time. Implement it the simple way first then see if you really have a problem with 'overloading the main Selector' ...

  • How can I use a Selector in a thread safe way?

    Hello,
    I'm using a server socket with a java.nio.channels.Selector contemporarily by 3 different threads (this number may change in the future).
    From the javadoc: Selectors are themselves safe for use by multiple concurrent threads; their key sets, however, are not.
    Following this advise, I wrote code in this way:
             List keys = new LinkedList(); //private key list for each thread
             while (true) {
              keys.clear();
              synchronized(selector) {
                  int num = selector.select();
                  if (num == 0)
                   continue;
                  Set selectedKeys = selector.selectedKeys();
                  //I expected this code to produce disjoint key sets on each thread...
                  keys.addAll(selectedKeys);
                  selectedKeys.clear();
              Iterator it = keys.iterator();
              while (it.hasNext()) {
                  SelectionKey key = (SelectionKey) it.next();
                  if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
                   Socket s = serverSocket.accept();
                   SocketChannel sc = s.getChannel();
                   sc.configureBlocking( false );
                   sc.register( selector, SelectionKey.OP_READ );
                  } else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
    //.....Unfortunately synchronizing on the selector didn't have the effect I expected. When another thread select()s, it sees the same key list as the other thread that select()ed previously. When control arrives to serverSocket.accept(), one thread goes ahead and the other two catch an IllegalBlockingModeException.
    I'm not willing to handle this exception, the right thing to do is giving disjoint key sets to each thread. How can I achieve this goal?
    Thanks in advance

    A single thread won't be enough cause after reading data from the socket I do some processing on it that may take long.So despatch that processing to a separate thread.
    Most of this processing is I/O boundI/O bound on the socket? or something else? If it's I/O bound on the socket that's even more of a reason to use a single thread.
    Anyway I think I'll use a single thread with the selector, put incoming data in a queue and let other 2 or 3 threads read from it.Precisely. Ditto outbound data.
    Thanks for your replies. But I'm still curious: why is a selector thread safe if it can't be used with multiple threads because of it's semantics?It can, but there are synchronization issues to overcome (with Selector.wakeup()), and generally the cost of solving these is much higher than the cost of a single-threaded selector solution with worker threads for the application processing.

  • Error SocketChannel receive multiple messages at once?

    Hello,
    I use Java NIO, non blocking for my client-server program.
    Everything works ok, until there are many clients that sending messages at the same time to the server.
    The server can identify all the clients, and begin reading, but the reading of those multiple clients are always the same message.
    For example, client A send "Message A", client B send "Missing Message", client C send "Another Missing Message" at the same time to the server, the server read client A send "Message A", client B send "Message A", client C send "Message A", only happen if the server trying to read all those messages at once, if the server read one by one, it's working perfectly.
    What's wrong with my code?
    This is on the server, reading the message:
    private Selector               packetReader; // the selector to read client message
    public void update(long elapsedTime) throws IOException {
      if (packetReader.selectNow() > 0) {
        // message received
        Iterator packetIterator = packetReader.selectedKeys().iterator();
        while (packetIterator.hasNext()) {
          SelectionKey key = (SelectionKey) packetIterator.next();
          packetIterator.remove();
          // there is client sending message, looping until all clients message
          // fully read
          // construct packet
          TCPClient client = (TCPClient) key.attachment();
          try {
            client.read(); // IN HERE ALL THE CLIENTS READ THE SAME MESSAGES
               // if only one client send message, it's working, if there are multiple selector key, the message screwed
          } catch (IOException ex) {
    //      ex.printStackTrace();
            removeClient(client); // something not right, kick this client
    }On the client, I think this is the culprit :
    private ByteBuffer            readBuffer; // the byte buffer
    private SocketChannel  client; // the client SocketChannel
    protected synchronized void read() throws IOException {
      readBuffer.clear();    // clear previous buffer
      int bytesRead = client.read(readBuffer);  // THIS ONE READ THE SAME MESSAGES, I think this is the culprit
      if (bytesRead < 0) {
        throw new IOException("Reached end of stream");
      } else if (bytesRead == 0) {
        return;
      // write to storage (DataInputStream input field storage)
      storage.write(readBuffer.array(), 0, bytesRead);
      // in here the construction of the buffer to real message
    }How could the next client read not from the beginning of the received message but to its actual message (client.read(readBuffer)), i'm thinking to use SocketChannel.read(ByteBuffer[] dsts, , int offset, int length) but don't know the offset, the length, and what's that for :(
    Anyone networking gurus, please help...
    Thank you very much.

    Hello ejp, thanks for the reply.
    (1) You can't assume that each read delivers an entire message.Yep I know about this, like I'm saying everything is okay when all the clients send the message not in the same time, but when the server tries to read client message at the same time, for example there are 3 clients message arrive at the same time and the server tries to read it, the server construct all the message exactly like the first message arrived.
    This is the actual construction of the message, read the length of the packet first, then construct the message into DataInputStream, and read the message from it:
    // packet stream reader
    private DataInputStream input;
    private NewPipedOutputStream storage;
    private boolean     waitingForLength = true;
    private int length;     
    protected synchronized void read() throws IOException {
      readBuffer.clear(); // clear previous byte buffer
      int bytesRead = client.read(readBuffer); // read how many bytes read
      if (bytesRead < 0) {
        throw new IOException("Reached end of stream");
      } else if (bytesRead == 0) {
        return;
      // the bytes read is used to fill the byte buffer
      storage.write(readBuffer.array(), 0, bytesRead);
      // after read the packet
      // this is the message construction
      // write to byte buffer to input storage
      // (this will write into DataInputStream)
      storage.write(readBuffer.array(), 0, bytesRead);
      // unpack the packet
      while (input.available() > 0) {
        // unpack the byte length first
        if (waitingForLength) { // read the packet length first
          if (input.available() > 2) {
            length = input.readShort();
            waitingForLength = false;
          } else {
            // the length has not fully read
            break; // wait until the next read
        // construct the packet if the length already known
        } else {
          if (input.available() >= length) {
            // store the content to data
            byte[] data = new byte[length];
            input.readFully(data);
            // add to received packet
            addReceivedPacket(data);
         waitingForLength = true; // wait for another packet
          } else {
            // the content has not fully read
         break; // wait until next read
    (2) You're sharing the same ByteBuffer between all your clients
    so you're running some considerable risks if (1) doesn't happen.
    I recommend you run a ByteBuffer per client and have a good look
    at its API and the NIO examples.Yep, I already use one ByteBuffer per client, it's not shared among the clients, this is the class for each client:
    private SocketChannel client; // socket channel per client
    private ByteBuffer readBuffer; // byte buffer per client
    private Selector packetReader; // the selector that is shared among all clients
    private static final int BUFFER_SIZE = 10240; // default huge buffer size for reading
    private void init() throws IOException {
      storage; // the packet storage writer
      input; // the actual packet input
      readBuffer = ByteBuffer.allocate(BUFFER_SIZE); // the byte buffer is one per client
      readBuffer.order(ByteOrder.BIG_ENDIAN);
      client.configureBlocking(false);
      client.socket().setTcpNoDelay(true);
      // register packet reader
      // one packetReader used by all clients
      client.register(packetReader, SelectionKey.OP_READ, this);
    }Cos the ByteBuffer is not shared, I think it's impossible that it mixed up with other clients, what I think is the SocketChannel client.read(ByteBuffer) that fill the byte buffer with the same packet?
    So you're probably getting the data all mixed up - you'll probalby be seeing a new client message followed by whatever was there from the last time, or the time before.If the server not trying to read all the messages at the same time, it works fine, I think that if the client SocketChannel filled up with multiple client messages, the SocketChannel.read(...) only read the first client message.
    Or am I doing something wrong, I could fasten the server read by removing the Thread.sleep(100); but I think that's not the good solution, since in NIO there should be time where the server need to read client multiple messages at once.
    Any other thoughts?
    Thanks again.

  • Client management with nio

    Hi everyone!
    I have a program based on nio which has a selector thread that handles the accepts and reads fromt he clients. Another thread, the main one, get's all the read information, handles it and sometimes has to send something back. Now I wonder how I should manage the clients so that I can send something to them based on their ip and what I have to look after to not get into dead locks or similar.
    Thanks for any help in advance!
    Chris

    The select loop in that example I
    posted passes the key to the doRead, doWrite and
    doAccept methods based on what is ready, they do the
    cast.I'm doing it like in your example for reading only. I thought that the trigger for the ON_WRITE select was a call to the write method of a SocketChannel so I tried to do it without the ON_WRITE stuff. Isn't the ON_WRITE select only for safety reasons when write could fail or block? I'm willing to do as you have suggested (with ON_WRITE) but I don't know how to trigger it..
    I have an example of a simple NIO multiple destination
    message switch (a bit like chat) that I will tidy up
    and post. It addresses the issues you are concerned
    with.That sounds awesome. I hope you get it up soon ;)
    Thanks for your help,
    Chris

  • Nio demo program on local loopback, how to?

    I'd like to write a small program as an educational material which could show the advantage of using nio scalable server I/O over traditional multi-threaded server architecture. The program should run on the local loopback connection, i.e. localhost. What could be the best approach for that kind of program? A simple client program once I wrote which dispatches multiple client threads accessing NIOEchoServer from EJP's book threw an 'IOException:too many open files' around 1000 or so concurrent client connections.

    That's a platform limitation. Probably nothing wrong with the code. Here's a simple NIO server that demonstrates correct use of OP_WRITE and also the Reactor pattern.
    * EchoServer.java
    * Created on 5 March 2008, 09:59
    * Copyright (c) Esmond Pitt, 2007. All rights reserved.
    package com.verismart.net;
    import java.io.Closeable;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.nio.ByteBuffer;
    import java.nio.channels.ClosedSelectorException;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    * A simple NIO echo server. This demonstrates the correct use of NIO in
    * a very simple context, specifically the correct use of OP_ACCEPT, OP_READ, and OP_WRITE,
    * and also demonstrates the Reactor pattern.
    * @author Esmond Pitt
    * @version $Revision: 4 $
    public class EchoServer implements Closeable, Runnable
         private static final Map<Integer, String> operations = new HashMap<Integer, String>();
         private Logger     logger = Logger.getLogger(this.getClass().getName());
         private ServerSocketChannel     ssc;
         private Selector     selector;
          * Creates a new instance of EchoServer.
          * @param port Port number to listen at.
         public EchoServer(int port) throws IOException
              this.ssc = ServerSocketChannel.open();
              this.selector = Selector.open();
              ssc.socket().bind(new InetSocketAddress(port));
              ssc.configureBlocking(false);
              ssc.register(selector, SelectionKey.OP_ACCEPT, new Acceptor());
         static
              operations.put(SelectionKey.OP_ACCEPT, "OP_ACCEPT");
              operations.put(SelectionKey.OP_CONNECT, "OP_CONNECT");
              operations.put(SelectionKey.OP_READ, "OP_READ");
              operations.put(SelectionKey.OP_WRITE, "OP_WRITE");
         static String     getOperations(int ops)
              String     result = "";
              for (int i = 1; i < 32; i <<= 1)
                   if ((ops & i) == 0)
                        continue;
                   if (result.length() > 0)
                        result += ",";
                   result += operations.get(i);
              return result;
         public void     close() throws IOException
              ssc.close();
              selector.close();
         public void run()
              while (selector.isOpen())
                   try
                        int     nsel = selector.select(timeout);
                        if (nsel == 0)
                             // TODO: timeout
                             for (SelectionKey key : selector.keys())
                                  logger.log(Level.INFO, "channel "+key.channel()+" waiting for "+getOperations(key.interestOps()));
                             continue;
                        Iterator<SelectionKey>     it = selector.selectedKeys().iterator();
                        while (it.hasNext())
                             SelectionKey     key = it.next();
                             it.remove();
                             if (!key.isValid() || !key.channel().isOpen())
                                  // e.g. OP_ACCEPT is triggered once when the channel is closed.
                                  continue;
                             Reactor     reactor = (Reactor)key.attachment();
                             try
                                  reactor.react(key);
                             catch (IOException exc)
                                  logger.log(Level.SEVERE, "calling Reactor.react()", exc);
                   catch (ClosedSelectorException exc)
                        logger.log(Level.FINE, "select loop", exc);
                   catch (IOException exc)
                        logger.log(Level.SEVERE, "select loop", exc);
         // A simple implementation of the Reactor pattern
          * Reactor interface.
         public interface Reactor
               * React to an NIO event.
               * @param key SelectionKey which has a ready operation.
              void     react(SelectionKey key) throws IOException;
          * Acceptor reactor. Accepts connections and registers them for OP_READ with a Reader reactor.
         public class Acceptor implements Reactor
              public void     react(SelectionKey key) throws IOException
                   ServerSocketChannel     ssc = (ServerSocketChannel)key.channel();
                   SocketChannel     sc = ssc.accept();
                   if (sc != null)
                        logger.log(Level.FINE, "accepted {0}", sc);
                        sc.configureBlocking(false);
                        sc.register(key.selector(), SelectionKey.OP_READ, new Reader(ByteBuffer.allocate(1024)));
          * Reader reactor. Handles OP_READ by echoing the data back to the sender.
          * Handles 0-length writes by registering OP_WRITE with a Writer reactor.
         public class Reader implements Reactor
              ByteBuffer          buffer;
               * Constructs a Reader.
               * @param buffer ByteBuffer for I/O.
              public Reader(ByteBuffer buffer)
                   this.buffer = buffer;
              public void     react(SelectionKey key) throws IOException
                   SocketChannel     sc = (SocketChannel)key.channel();
                   int     count;
                   while ((count = sc.read(buffer)) > 0 || buffer.position() > 0)
                        logger.log(Level.FINE, "read {0} bytes from {1}", new Object[]{count, sc});
                        try
                             buffer.flip();
                             count = sc.write(buffer);
                             logger.log(Level.FINE, "wrote {0} bytes to {1}", new Object[]{count, sc});
                             if (count == 0)
                                  // Stop reading this channel and wait for an OP_WRITE
                                  sc.register(key.selector(), SelectionKey.OP_WRITE, new Writer(buffer));
                                  return;
                        finally
                             buffer.compact();
                   if (count < 0)
                        logger.log(Level.FINE, "read EOS from {0}", new Object[]{sc});
                        sc.close();
          * Writer reactor. Handles OP_WRITE by writing the buffer to the reacting channel.
          * When writing is complete, registers OP_READ with a Reader reactor.
         public class Writer implements Reactor
              ByteBuffer          buffer;
               * Constructs a Writer.
               * @param buffer ByteBuffer for I/O.
              public Writer(ByteBuffer buffer)
                   this.buffer = buffer;
              public void     react(SelectionKey key) throws IOException
                   try
                        SocketChannel     sc = (SocketChannel)key.channel();
                        buffer.flip();
                        int     count = sc.write(buffer);
                        logger.log(Level.FINE, "wrote {0} bytes to {1}", new Object[]{count, sc});
                        if (!buffer.hasRemaining())
                             // Nothing left to write: OK to start reading again
                             sc.register(key.selector(), SelectionKey.OP_READ, new Reader(buffer));
                   finally
                        buffer.compact();
          * Utility field used by bound properties.
         private java.beans.PropertyChangeSupport propertyChangeSupport =  new java.beans.PropertyChangeSupport(this);
          * Adds a PropertyChangeListener to the listener list.
          * @param l The listener to add.
         public void addPropertyChangeListener(java.beans.PropertyChangeListener l)
              propertyChangeSupport.addPropertyChangeListener(l);
          * Removes a PropertyChangeListener from the listener list.
          * @param l The listener to remove.
         public void removePropertyChangeListener(java.beans.PropertyChangeListener l)
              propertyChangeSupport.removePropertyChangeListener(l);
          * Holds value of property timeout.
         private int timeout;
          * Getter for property timeout.
          * @return Value of property timeout.
         public int getTimeout()
              return this.timeout;
          * Setter for property timeout.
          * @param timeout New value of property timeout.
         public void setTimeout(int timeout)
              int oldTimeout = this.timeout;
              this.timeout = timeout;
              propertyChangeSupport.firePropertyChange ("timeout", new Integer (oldTimeout), new Integer (timeout));
          * Main method, for testing.
          * @param args Command line arguments.
         public static void     main(String[] args) throws IOException
              int     port = args.length > 0 ? Integer.parseInt(args[0]) : 8082;
              EchoServer     server = new EchoServer(port);
              server.setTimeout(10*1000);
              new Thread(server).start();
              if (true)
                   Socket     socket = new Socket("localhost", port);
                   socket.getOutputStream().write("hello".getBytes());
                   System.out.println("wrote hello to "+socket);
                   byte[]     buffer = new byte[8192];
                   int     count = socket.getInputStream().read(buffer);
                   System.out.println("read "+new String(buffer,0,count)+" from "+socket);
                   socket.close();
                   server.close();
    }

  • After SocketChannel.close, must call Selector.wakeup

    When I am reading from a tcp socket using NIO channels & selectors, I have the following problem when I go to close the channel.
    If I close the channel in the thread where I called selector.select(), then the channel is closed and the client application gets the event that the channel was closed.
    However, if I do the reading in a seperate thread, after calling channel.close(), I must call selector.wakeup() or the socket is not closed.
    Any idea what is going on?
    thanks - dave

    The main point of NIO is that you don't need multiple threads to read and write multiple sockets. You can use multiple threads, but it complicates things. After you close a channel you must let the select run one more time, this is the reason that I try to close channels from the thread that is running the select. You probably already have a queue of runnables to process interestOps and register in the select thread. You should use that for the close activity as well.
    I've posted a lot of topics on NIO, that cover this and other tricks of using NIO. Here are the most useful.
    Taming the NIO Circus, NIO Server Example, NIO Client Example

  • Java.nio select() method return 0 in my client application

    Hello,
    I'm developing a simple chat application who echo messages
    But my client application loop because the select() method return 0
    This is my code
    // SERVER
    package test;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.Iterator;
    import java.util.Set;
    public class Server {
         private int port = 5001;
         public void work() {               
              try {
                   ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
                   serverSocketChannel.configureBlocking(false);
                   InetSocketAddress isa = new InetSocketAddress(port);               
                   serverSocketChannel.socket().bind(isa);
                   Selector selector = Selector.open();
                   serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
                   System.out.println("Listing on "+port);
                   while(selector.select()>0) {
                        Set keys = selector.selectedKeys();
                        for(Iterator i = keys.iterator(); i.hasNext();) {
                             SelectionKey key = (SelectionKey) i.next();
                             i.remove();
                             if (key.isAcceptable()) {
                                  ServerSocketChannel keyChannel = (ServerSocketChannel)key.channel();                              
                                  SocketChannel channel = keyChannel.accept();
                                  channel.configureBlocking(false);                              
                                  channel.register(selector, SelectionKey.OP_READ );
                             } else if (key.isReadable()) {
                                  SocketChannel keyChannel = (SocketChannel) key.channel();
                                  String m = Help.read(keyChannel );
                                  Help.write(m.toUpperCase(), keyChannel );
              } catch (IOException e) {                                             
                   e.printStackTrace();                         
         public static void main(String[] args) {
              Server s = new Server();
              s.work();
    // CLIENT
    package test;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    import java.util.Iterator;
    import java.util.Set;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    public class Client extends JFrame  {
         private String host = "localhost";
         private int port = 5001;
         private SocketChannel socketChannel;
         private Selector selector;
         public void work() {               
              try {
                   socketChannel = SocketChannel.open();
                   socketChannel.configureBlocking(false);
                   InetSocketAddress isa = new InetSocketAddress(host, port);               
                   socketChannel.connect(isa);
                   selector = Selector.open();
                   socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ );
                   while(true) {
                        selector.select();
                        Set keys = selector.selectedKeys();
                        for(Iterator i = keys.iterator(); i.hasNext();) {
                             SelectionKey key = (SelectionKey) i.next();
                             i.remove();
                             if (key.isConnectable()) {
                                  SocketChannel keyChannel = (SocketChannel) key.channel();
                                  if (keyChannel.isConnectionPending()) {
                                       System.out.println("Connected "+keyChannel.finishConnect());                                                                           
                             } else if (key.isReadable()) {                                                                                                                                                           
                                  SocketChannel keyChannel = (SocketChannel) key.channel();                                             
                                  String m = Help.read(keyChannel);
                                  display(m);                                                                                                                                                                                                                   
              } catch (IOException e) {                                             
                   e.printStackTrace();                         
         private void display(final String m) {
              SwingUtilities.invokeLater(new Runnable() {
                   public void run() {
                        area.append(m+"\n");
                        textFieed.setText("");
         private void sendMessage(final String m) {
              Thread t = new Thread(new Runnable() {               
                   public void run() {                                                                                
                        try {                         
                             Help.write(m, socketChannel);
                        } catch (IOException e) {               
                             e.printStackTrace();
              t.start();                    
         public Client() {
              addWindowListener(new WindowAdapter() {
                   public void windowClosing(WindowEvent e) {
                        System.exit(1);
              textFieed.addKeyListener(new KeyAdapter() {
                   public void keyPressed(KeyEvent e) {
                        if (e.getKeyCode()== KeyEvent.VK_ENTER) {
                             String m = textFieed.getText();
                             sendMessage(m);     
              area.setEditable(false);
              getContentPane().add(textFieed, "North");
              getContentPane().add(new JScrollPane(area));
              setBounds(200, 200, 400, 300);
              show();
         private String messageToSend;
         private JTextArea area = new JTextArea();
         JTextField textFieed = new JTextField();
         public static void main(String[] args) {
              Client s = new Client();
              s.work();
    // HELPER CLASS
    package test;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.channels.SocketChannel;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import java.nio.charset.CharsetEncoder;
    public class Help {
         private static Charset charset = Charset.forName("us-ascii");
         private static CharsetEncoder enc = charset.newEncoder();
         private static CharsetDecoder dec = charset.newDecoder();
         private static void log(String m) {
              System.out.println(m);
         public static String read(SocketChannel channel) throws IOException {
              log("*** start READ");                              
              int n;
              ByteBuffer buffer = ByteBuffer.allocate(1024);
              while((n = channel.read(buffer)) > 0) {
                   System.out.println("     adding "+n+" bytes");
              log("  BUFFER REMPLI : "+buffer);
              buffer.flip();               
              CharBuffer cb = dec.decode(buffer);          
              log("  CHARBUFFER : "+cb);
              String m = cb.toString();
              log("  MESSAGE : "+m);          
              log("*** end READ");
              //buffer.clear();
              return m;                    
         public static void write(String m, SocketChannel channel) throws IOException {          
              log("xxx start WRITE");          
              CharBuffer cb = CharBuffer.wrap(m);
              log("  CHARBUFFER : "+cb);          
              ByteBuffer  buffer = enc.encode(cb);
              log("  BUFFER ALLOUE REMPLI : "+buffer);
              int n;
              while(buffer.hasRemaining()) {
                   n = channel.write(buffer);                         
              System.out.println("  REMAINING : "+buffer.hasRemaining());
              log("xxx end WRITE");

    Here's the fix for that old problem. Change the work method to do the following
    - don't register interest in things that can't happen
    - when you connect register based on whether the connection is complete or pending.
    - add the OP_READ interest once the connection is complete.
    This doesn't fix all the other problems this code will have,
    eg.
    - what happens if a write is incomplete?
    - why does my code loop if I add OP_WRITE interest?
    - why does my interestOps or register method block?
    For code that answers all those questions see my obese post Taming the NIO Circus
    Here's the fixed up Client code
    // CLIENT
    package test
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    import java.util.Iterator;
    import java.util.Set;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    public class Client extends JFrame  {
         private String host = "localhost";
         private int port = 5001;
         private SocketChannel socketChannel;
         private Selector selector;
         public void work() {
              try {
                   socketChannel = SocketChannel.open();
                   socketChannel.configureBlocking(false);
                   InetSocketAddress isa = new InetSocketAddress(host, port);
                   socketChannel.connect(isa);
                   selector = Selector.open();
                   int interest = 0;
                   if(socketChannel.isConnected())interest = SelectionKey.OP_READ;
                   else if(socketChannel.isConnectionPending())interest = SelectionKey.OP_CONNECT;
                   socketChannel.register(selector, interest);
                   while(true)
                        int nn = selector.select();
                        System.out.println("nn="+nn);
                        Set keys = selector.selectedKeys();
                        for(Iterator i = keys.iterator(); i.hasNext();)
                             SelectionKey key = (SelectionKey) i.next();
                             i.remove();
                             if (key.isConnectable())
                                  SocketChannel keyChannel = (SocketChannel) key.channel();
                                  System.out.println("Connected "+keyChannel.finishConnect());
                                  key.interestOps(SelectionKey.OP_READ);
                             if (key.isReadable())
                                  SocketChannel keyChannel = (SocketChannel) key.channel();
                                  String m = Help.read(keyChannel);
                                  display(m);
              } catch (IOException e) {
                   e.printStackTrace();
         private void display(final String m) {
              SwingUtilities.invokeLater(new Runnable() {
                   public void run() {
                        area.append(m+"\n");
                        textFieed.setText("");
         private void sendMessage(final String m) {
              Thread t = new Thread(new Runnable() {
                   public void run() {
                        try {
                             Help.write(m, socketChannel);
                        } catch (IOException e) {
                             e.printStackTrace();
              t.start();
         public Client() {
              addWindowListener(new WindowAdapter() {
                   public void windowClosing(WindowEvent e) {
                        System.exit(1);
              textFieed.addKeyListener(new KeyAdapter() {
                   public void keyPressed(KeyEvent e) {
                        if (e.getKeyCode()== KeyEvent.VK_ENTER) {
                             String m = textFieed.getText();
                             sendMessage(m);
              area.setEditable(false);
              getContentPane().add(textFieed, "North");
              getContentPane().add(new JScrollPane(area));
              setBounds(200, 200, 400, 300);
              show();
         private String messageToSend;
         private JTextArea area = new JTextArea();
         JTextField textFieed = new JTextField();
         public static void main(String[] args) {
              Client s = new Client();
              s.work();

Maybe you are looking for

  • Recordset per message in Sender File Adapter

    Hi Friends I have configured a sender file adapter to pick up *.txt files from a specific path, Since the file is having thousands of records it is failing to process the file at  PI level . In order to avoid the problem I have kept Recordset Set Per

  • Purchase order Acknowledgement not create in SRM?

    Hi there, We are able to create Purchase order in SRM, but we don't see PO Ack generated. How do we set up PO Ack in SRM? Are we missing some configurations? Any help is appreciated. Thanks, Karma

  • AP PERIOD을 CLOSE할수 없는 경우

    제품 : FIN_AP 작성날짜 : 2003-05-15 AP PERIOD을 CLOSE할수 없는 경우 ======================== PURPOSE 닫히지 않는 AP PERIOD을 닫는다. Problem Description fact: APXSUMPS - Control Period Statuses symptom: AP Accounting Period를 close할수 없음 symptom: 다음의 에러 발생: APP-SQLAP-10741:

  • Movie keeps stopping after 45 clicks

    Hi, My flash movie keeps stopping after I've clicked 45 times and I've no idea why. There are lots of buttons on the page and when you click them they count how many times the buttons has been clicked and display this in a dynamic text box underneath

  • HT3576 Old deleted emails are in my notifications center and There is no option to remove them.......I have over 100 in there and want them gone....

    I have the same issue with my iPhone.....when I pull up the notification screen and type in a letter in the search column, it brings up some info plus over a hundred old emails that I have deleted on my iPad as well as my main computer......some of t