Non-blocking ServerSocketChannel.accept()

This may be a dumb question, but what would the motivation be behind utilizing a non-blocking call to the accept method of the ServerSocketChannel? I'm just having a hard time thinking of any, although I'm sure there are good reasons for doing it.
Thanks,
Ken

it does seem pretty strange

Similar Messages

  • Non-blocking accept()

    Does Java provide any way to implement a non-blocking accept()?

    There is no 'more or less' about it, it can be done. See java.nio.channels.ServerSocketChannel.
    You could also set a very short timeout on a ServerSocket if you don't want the entire NIO circus ...

  • SO timeout relevance in non-blocking NIO ServerSocketChannel

    I converted a threaded blocking server from using the standard blocking IO with a thread for each connection to using non-blocking NIO channels. Works great but I'm trying to understand the SO timeout relevance in the context of non-blocking NIO channels. Is there any relevance and should I set an SO timeout on the ServerSocket associated with a ServerSocketChannel and if so how should I handle it?

    No. Socket timeouts are for blocking mode. If you need timeouts in non-blocking mode you have to do them yourself, taking advantage of the Selector.select(long timeout) method and keeping track of activity times per channel yourself. You should use that select() method anyway, rather than just blocking indefinitely, as it gives you a chance to catch up on housekeeping, dead channels, etc. For example as a very naive approach if nothing happens in say a select timeout of 10 minutes you might want to close all accepted SocketChannels.

  • Non-blocking SocketChannels

    I'm trying to learn how to use non-blocking socket channles, but I haven't found much info (nor luck) so far.
    To learn, I'm building a server and a client. The server accepts input from the clients and process it in only one thread. The clients should send Objects to the server, and the server process them and return the result also as an Object. For this, I'm trying to use ObjectOutputStream and ObjectInputStream.
    The problem I don't know how to solve is that the SocketChannel is in non-bolcking mode, so I can't use their input/output streams (I get a IllegalBlockingModeException). In the server process loop I can reconfigure the SocketChannel to blocking mode to be able to read the Object, but I can't configure it to non-blocking mode again because I get a CancelledKeyException.
    Does anyone know how to work with InputStreams and non-blocking channels? Or where to find more info about it?
    Here are the relevant part of the server code:
    Set ready = selector.selectedKeys();
    Iterator i = ready.iterator();
    while (i.hasNext()) {
       try {
          SelectionKey sk = i.next();
          i.remove();
          if (sk.isAcceptable()) {
             ServerSocketChannel ssc = (ServerSocketChannel)sk.channel();
             SocketChannel sc = ssc.accept();
             sc.configureBlocking(false);
             sc.register(selector, SelectionKey.OP_READ);
          } else if (sk.isReadable()) {
             SocketChannel sc = (SocketChannel)sk.channel();
             // PROBLEM: If the channel is in non-blocking mode
             // I cannot use InputStreams
             sk.cancel();
             sc.configureBlocking(true);
             // Read the object sent by the client
             ObjectInputStream in = new ObjectInputStream(Channels.newInputStream(sc));
             Object o = in.readObject();
             // PROBLEM: Can't put the channel back to non-blocking mode
             sc.configureBlocking(false);
             sc.register(selector, SelectionKey.OP_READ); // CancelledKeyException
       } catch (...){
    }

    In my client, this is working fine:
    ObjectOutputStream oos = null;
    ObjectInputStream ois = null;
    for (int i = 0; i < 30000; i++) {
       oos = new ObjectOutputStream(sc.socket().getOutputStream());
       oos.writeObject(object);
       oos.flush();
       ois = new ObjectInputStream(sc.socket().getInputStream());
       Object o = ois.readObject();
    }But trying to do it like this throws a StreamCorruptedException at the server side.
    ObjectOutputStream oos = new ObjectOutputStream(sc.socket().getOutputStream());
    ObjectInputStream ois = new ObjectInputStream(sc.socket().getInputStream());
    for (int i = 0; i < 30000; i++) {
       oos.writeObject(object);
       oos.flush();
       Object o = ois.readObject();
    }Do you know why?

  • NIO Non-Blocking Server not Reading from Key

    I have created a NIO non blocking server (below) and it will not pick up any input from the client.... My log doesnt even show that it enters the readKey() method, so it must be something before. Any help would be appreciated.
    Scott
    package jamb.server;
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.channels.ClosedChannelException;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.channels.spi.SelectorProvider;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import java.util.Iterator;
    import java.util.Set;
    import java.util.logging.Logger;
    import java.util.prefs.Preferences;
    import jamb.server.client.Client;
    public class Server {
            private Selector selector;
            private ServerSocketChannel serverChannel;
            private static Logger logger = Logger.getLogger("jamb.server");
            private static Preferences prefs =  Preferences.systemRoot().node("/jamb/server");
            public void init() {
                    logger.entering("jamb.server.Server", "init");
                    //Get a selector...
                    try {
                            selector = SelectorProvider.provider().openSelector();
                            //Open the SocketChannel and make it non-blocking...
                            serverChannel = ServerSocketChannel.open();
                         serverChannel.configureBlocking(false);
                            //Bind the server to the port....
                            int port = prefs.getInt("Port", 4000);
                            logger.config("Server configured on port " + port + " (default: 4000)");
                         InetSocketAddress isa = new InetSocketAddress(
                                    InetAddress.getLocalHost(), port);       
                         serverChannel.socket().bind(isa);
                    } catch (IOException ioe) {
                            logger.severe ("IOException during server initialization!");
                    logger.exiting("jamb.server.Server", "init");
            public void run() {
                    logger.entering("jamb.server.Server", "run");
                    int bufferSize = prefs.getInt("BufferSize", 8);
                    logger.config("Buffer size set to " + bufferSize + " (default: 8)");
                    SelectionKey acceptKey = null;
                    try {
                            acceptKey = serverChannel.register(
                                    selector, SelectionKey.OP_ACCEPT);
                    } catch (ClosedChannelException cce) {
                    try {
                            while (acceptKey.selector().select() > 0) {
                                    Set readyKeys = selector.selectedKeys();
                                    Iterator i = readyKeys.iterator();
                                    while (i.hasNext()) {
                                            //logger.finest("Processing keys...");
                                            //Get the key from the set and remove it
                                            SelectionKey currentKey = (SelectionKey) i.next();
                                            i.remove();
                                            if (currentKey.isAcceptable()) {
                                                    logger.finest("Accepting key...");
                                                    acceptKey(currentKey);
                                            } else if (currentKey.isReadable()) {
                                                    logger.finest("Reading key...");
                                                    readKey(currentKey, bufferSize);
                                            } else if (currentKey.isWritable()) {
                                                    //logger.finest("Writing key...");
                                                    writeKey(currentKey);
                    } catch (IOException ioe) {
                            logger.warning("IOException during key handling!");
                    logger.exiting("jamb.server.Server", "run");
            public void flushClient (Client client) {
                    try {
                            ByteBuffer buf = ByteBuffer.wrap( client.getOutputBuffer().toString().getBytes());
                            client.getChannel().write(buf);
                    } catch (IOException ioe) {
                            System.out.println ("Error writing to player");
                    client.setOutputBuffer(new StringBuffer());
            private void acceptKey (SelectionKey acceptKey) {
                    logger.entering("jamb.server.Server", "acceptKey");
                    //Retrieve a SocketChannel for the new client, and register a new selector with
                    //read/write interests, and then register
                    try {
                            SocketChannel channel =  ((ServerSocketChannel) acceptKey.channel()).accept();
                            channel.configureBlocking(false);
                            SelectionKey readKey = channel.register(
                                    selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE  );
                            readKey.attach(new Client(this, channel));
                    } catch (IOException ioe) {
                            System.out.println ("Error accepting key");
                    logger.exiting("jamb.server.Server", "acceptKey");
            private void readKey (SelectionKey readKey, int bufSize) {
                    logger.entering("jamb.server.Server", "readKey");
                    Client client = (Client) readKey.attachment();
                    try {
                            ByteBuffer byteBuffer = ByteBuffer.allocate(bufSize);
                            int nbytes = client.getChannel().read( byteBuffer );
                            byteBuffer.flip();
                            Charset charset = Charset.forName( "us-ascii" );
                            CharsetDecoder decoder = charset.newDecoder();
                            CharBuffer charBuffer = decoder.decode(byteBuffer);
                            String text = charBuffer.toString();
                            client.getInputBuffer().append(text);
                            if ( text.indexOf( "\n" ) >= 0 )
                                    client.input();
                    } catch (IOException ioe) {
                            logger.warning("Unexpected quit...");
                            client.disconnect();
                    logger.exiting("jamb.server.Server", "readKey");
            private void writeKey (SelectionKey writeKey) {
                    //logger.entering("jamb.server.Server", "writeKey");
                    Client client = (Client) writeKey.attachment();
                    if (!client.isConnected()) {
                            client.connect();
                    //logger.exiting("jamb.server.Server", "writeKey");

    From my own expierence with the NIO (Under Windows XP/ jdk1.4.1_01); you can't seem to set READ and WRITE at the same time.
    The program flow I usually end up with for a echo server is:
    When the selector.isAcceptable(): accept a connection; register for READs
    In the read event; write the incoming characters to a buffer; register for a WRITE and add the buffer as an attachment.
    In the write event; write the data to the socket If all the data was written; register for a READ; otherwise register for another WRITE so that you can write the rest.
    Not sure if that the "proper" way; but it works well for me.
    - Chris

  • Non-blocking socket concurrent limitation?

    I have 2 socket program,one is server side used nio package with JDK1.4.1,the other is client used traditional socket,the client will initialize about 50
    threads trying to connect with server when starting,but only about 15
    can be accepted,these 2 program are runnning in the same computer which
    OS is win2000 professional PC.
    the followd is these code:
    please make a probe with them ,and tell me what's going on?
    server:
    package nio_select_demo;
    import java.io.*;
    import java.net.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.util.*;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    public class Server implements Runnable
    // The port we will listen on
    private int port;
    // A pre-allocated buffer for processing data
    private final ByteBuffer buffer = ByteBuffer.allocate( 16384 );
    private ByteBuffer resBuf = ByteBuffer.allocate( 128 );
    Selector selector;
    AddInfo test ;
    public Server( int port ) {
    this.port = port;
    // for (int i=0; i<threadnum; ++i) {
    new Thread( this ).start();
    test = new AddInfo();
    test.start();
    public void run() {
    try {
    // create a ServerSocketChannel
    ServerSocketChannel ssc1 = ServerSocketChannel.open();
    // ServerSocketChannel ssc2 = ServerSocketChannel.open();
    // Set it to non-blocking
    ssc1.configureBlocking( false );
    // Get the Socket connected to this channel, and bind it
    // to the listening port
    ServerSocket ss = ssc1.socket();
    InetSocketAddress isa = new InetSocketAddress( port );
    ss.bind( isa , 60 );
    // Create a new Selector for selecting
    selector = Selector.open();
    // Register the ServerSocketChannel, so we can
    // listen for incoming connections
    ssc1.register( selector, SelectionKey.OP_ACCEPT );
    System.out.println( "Listening on port "+port );
    int n = 0;
    while (true) {
    // See if we've had any activity -- either
    // an incoming connection, or incoming data on an
    // existing connection
    int num = selector.select();
    // If we don't have any activity, loop around and wait
    // again
    if (num == 0) {
    continue;
    // Get the keys corresponding to the activity
    // that has been detected, and process them
    // one by one
    Set keys = selector.selectedKeys();
    Iterator it = keys.iterator();
    while (it.hasNext()) {
    // Get a key representing one of bits of I/O
    // activity
    SelectionKey key = (SelectionKey)it.next();
    // What kind of activity is it?
    if ((key.readyOps() & SelectionKey.OP_ACCEPT) ==
    SelectionKey.OP_ACCEPT) {
    System.out.println( "accept request" );
    // It's an incoming connection.
    // Register this socket with the Selector
    // so we can listen for input on it
    SocketChannel sc = ((ServerSocketChannel)key.channel()).accept();
    System.out.println( "Got connection from "+sc.socket());
    // Make sure to make it non-blocking, so we can
    // use a selector on it.
    //SocketChannel sc = s.getChannel();
    sc.configureBlocking( false );
    // Register it with the selector, for reading
    sc.register( selector, SelectionKey.OP_READ| SelectionKey.OP_WRITE);
    } else if ((key.readyOps() & SelectionKey.OP_READ) ==
    SelectionKey.OP_READ) {
    //ssc.register(selector , SelectionKey.OP_READ);
    SocketChannel sc = null;
    try {
    // It's incoming data on a connection, so
    // process it
    sc = (SocketChannel)key.channel();
    Socket s1 = sc.socket();
    s1.setTcpNoDelay(true);
    System.out.println( "enter processing data" );
    boolean ok = processInput( key );
    synchronized (selector) {
    key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
    // If the connection is dead, then remove it
    // from the selector and close it
    if (!ok) {
    key.cancel();
    System.out.println("dead");
    Socket s = null;
    try {
    s = sc.socket();
    s.close();
    } catch( IOException ie ) {
    System.err.println( "Error closing socket "+s+": "+ie );
    } catch( IOException ie ) {
    ie.printStackTrace();
    // On exception, remove this channel from the selector
    key.cancel();
    System.err.println( "Error raised in this socket");
    try {
    sc.close();
    } catch( IOException ie2 ) { System.out.println( ie2 ); }
    System.out.println( "Closed "+sc );
    else if ((key.readyOps() & SelectionKey.OP_WRITE) ==
    SelectionKey.OP_WRITE) {
    System.out.println("Enter Writing");
    String response = new String();
    if((response=this.test.getInfo())!=null){
    resBuf.clear();
    SocketChannel sc = (SocketChannel)key.channel();
    resBuf = ByteBuffer.wrap( response.getBytes("ISO-8859-1" ) );
    sc.write( resBuf );
    synchronized (selector) {
    key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
    // We remove the selected keys, because we've dealt
    // with them.
    keys.clear();
    } catch( IOException ie ) {
    System.err.println( ie );
    private boolean processInput( SelectionKey key ) throws IOException {
    buffer.clear();
    SocketChannel sc = (SocketChannel)key.channel();
    sc.read( buffer );
    buffer.flip();
    String response = new String("response ok");
    // If no data, close the connection
    if (buffer.limit()==0) {
    return false;
    Charset charset=Charset.forName("ISO-8859-1");
    CharsetDecoder decoder = charset.newDecoder();
    CharBuffer charBuffer = decoder.decode(buffer);
    System.out.println(charBuffer.toString());
    System.out.println( "Processed "+buffer.limit()+" from "+sc );
    return true;
    static public void main( String args[] ) throws Exception {
    int port = Integer.parseInt( args[0] );
    System.out.println(port);
    new Server( port );
    cilent:
    import java.io.*;
    import java.net.*;
    import java.util.*;
    public class Client implements Runnable
    private String host;
    private int port;
    private int acport;
    //the size of buffer on how much we write and read per cycle
    private static final int maxWriteSize = 128;
    public Client( String host, int port, int numThreads ) {
    this.host = host;
    this.port = port;
    for(int i =0;i<50;i++){//initialize 50 client threads
    new Thread(this).start();
    public void run() {
    byte buffer[] = new byte[maxWriteSize];
    byte buffer2[] = new byte[maxWriteSize];
    try {
    Socket s = new Socket( );
    InetSocketAddress sa = new InetSocketAddress(host,this.port);
    s.connect(sa);
    System.out.println(s);
    s.setTcpNoDelay(true);
    InputStream in = s.getInputStream();
    OutputStream out = s.getOutputStream();
    for (int i=0; i<maxWriteSize; ++i) {
    buffer[i] = (byte)'a';
    out.write( buffer, 0, maxWriteSize );
    int pause = 500;
    in.read( buffer , 0 , maxWriteSize );
    System.out.println( Thread.currentThread()+" wrote "+maxWriteSize);
    String res = new String ( buffer );
    String res2 = new String ( buffer2 );
    System.out.println( res );
    try { Thread.sleep( pause ); } catch( InterruptedException ie ) {}
    } catch( Exception ie ) {
    ie.printStackTrace();
    System.err.println(ie.getMessage());
    static public void main( String args[] ) throws Exception {
    String host = "127.0.0.1";
    int port = Integer.parseInt( args[0] );
    int numThreads = Integer.parseInt( args[1] );
    new Client( host, port, numThreads );

    I have found the reason!!!
    because of system resource limitation,windows can't afford to maintain
    so many concurrent stream-IO,so some socket will be closed.
    I modified the client side code,adding thes segments to client instantialize
    such as :
    public Client( String host, int port, int numThreads ) {
    for(int i =0;i<1000;i++){
    new Thread(this).start();
    try {
    Thread.currentThread().sleep(100);//give system some idle
    } catch (InterruptedException e) {
    /* ignore */
    then the server can accept more than 1000 client request concurrently.

  • Non-Blocking I/O Implementation Issue

    Hi All,
    I am trying out the latest JDK 1.4 java.nio.* package. I modified the NBTimeServer and wrote a client which connects to the NBTimeServer and tries to pass messages to and fro. I always succeed to pass on roundtrip of msgs and then Server blocks my client forever. I have modified NBTimeServer to accomodate one client only. Any help or comments on this would be really appreciated. Code is below. Feel free to try it out if want to see what I am trying to convey in this message.
    /*******Server Code*******/
    Modified this code to test mulitple to and fro msgs between client and server.
    Only one client will ever be able to connect to this server during life of a server.
    My point here is to demonstrate the to and fro comm between one client and one server
    import java.io.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.channels.spi.*;
    import java.net.*;
    import java.util.*;
    import java.nio.charset.*;
    import java.util.regex.*;
    // Listen on a port for connections and write back the current time.
    public class NBTimeServer {
    private static final int DEFAULT_TIME_PORT = 8900;
    // Constructor with no arguments creates a time server on default port.
    public NBTimeServer() throws Exception {
         acceptConnections(this.DEFAULT_TIME_PORT);
    // Constructor with port argument creates a time server on specified port.
    public NBTimeServer(int port) throws Exception {
         acceptConnections(port);
    // Accept connections for current time. Lazy Exception thrown.
    private static void acceptConnections(int port) throws Exception {
         // Selector for incoming time requests
         Selector acceptSelector = SelectorProvider.provider().openSelector();
         Selector rwSelector = SelectorProvider.provider().openSelector();
         // Create a new server socket and set to non blocking mode
         ServerSocketChannel ssc = ServerSocketChannel.open();
         ssc.configureBlocking(false);
         // Bind the server socket to the local host and port
         InetAddress lh = InetAddress.getLocalHost();
         InetSocketAddress isa = new InetSocketAddress(lh, port);
         ssc.socket().bind(isa);
         // Register accepts on the server socket with the selector. This
         // step tells the selector that the socket wants to be put on the
         // ready list when accept operations occur, so allowing multiplexed
         // non-blocking I/O to take place.
         SelectionKey acceptKey = ssc.register(acceptSelector,
                             SelectionKey.OP_ACCEPT);
         int keysAdded = 0;
         // Here's where everything happens. The select method will
         // return when any operations registered above have occurred, the
         // thread has been interrupted, etc.
         while ((keysAdded = acceptSelector.select()) > 0) {
         // Someone is ready for I/O, get the ready keys
         Set readyKeys = acceptSelector.selectedKeys();
         Iterator i = readyKeys.iterator();
         // Walk through the ready keys collection and process date requests.
         while (i.hasNext()) {
              SelectionKey sk = (SelectionKey)i.next();
              i.remove();
              // The key indexes into the selector so you
              // can retrieve the socket that's ready for I/O
              ServerSocketChannel nextReady =
              (ServerSocketChannel)sk.channel();
              // Accept the date request and send back the date string
              Socket s = nextReady.accept();
                        SocketChannel sc = s.getChannel();
    System.out.println("Got client channel..");
              sc.configureBlocking(false);
              SelectionKey readKey = sc.register(rwSelector,
                             SelectionKey.OP_READ|SelectionKey.OP_WRITE);                     
              int count = 0;
    while(true) {
    if((count = rwSelector.select(1000L)) > 0) {
    Set readKeys = rwSelector.selectedKeys();
    Iterator i1 = readKeys.iterator();
    while(i1.hasNext()) {
    System.out.println("Loop in Iterator");
    SelectionKey sk1 = (SelectionKey)i1.next();
    i1.remove();
    if(sk1.isReadable()) {
    DataInputStream sin = new DataInputStream(new BufferedInputStream(s.getInputStream(), 4096));
    System.out.println(sin.readInt());
    if(sk1.isWritable()) {
    DataOutputStream sout = new DataOutputStream(new BufferedOutputStream(s.getOutputStream(), 4096));
    PrintWriter out = new PrintWriter(sout, true);
              Date now = new Date();
              out.println(now);
    // Entry point.
    public static void main(String[] args) {
         // Parse command line arguments and
         // create a new time server (no arguments yet)
         try {
              NBTimeServer nbt = new NBTimeServer();
         } catch(Exception e) {
              e.printStackTrace();          
    /******End Server Code********/
    /*****Begin Client Code********/
    import java.io.*;
    import java.net.*;
    import java.util.*;
    // Listen on a port for connections and write back the current time.
    public class NBTimeClient {
    private static final int DEFAULT_TIME_PORT = 8900;
    public static void main(String args[]) throws Exception {
    InetAddress lh = InetAddress.getLocalHost();
    Socket s = new Socket(lh, DEFAULT_TIME_PORT);
    DataInputStream din = new DataInputStream(new BufferedInputStream(s.getInputStream(), 4096));
    DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(s.getOutputStream(), 4096));
    //Read the time
    System.out.println(din.readLine());
    //send some junk which is read by server
    dout.writeInt(1299);
    dout.flush();
    //read time again -- I never get anything here and I am blocked here...
    System.out.println(din.readLine());
    //send some junk back to the server
    dout.writeInt(1299);
    dout.flush();
    s.close();
    /*******End Client Code**********/
    thanks,
    Xtrimity

    The reason it blocks forever is that you need to keep reusing your main select. That is where the non-blocking event will come from. Here is a bit of code that doesn't block forever.
    Tim
    http://tim.owlmountain.com
    import java.io.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.channels.spi.*;
    import java.net.*;
    import java.util.*;
    import org.apache.log4j.*;
    public class NBServer3 {
    int _port = 4000;
    Selector _selector = null;
    ServerSocketChannel _selectableChannel = null;
    int _keysAdded = 0;
    static Category log =
    Category.getInstance(NBServer3.class.getName());
    static String QUIT_SERVER = "quit";
    public NBServer3() {
    public NBServer3( int port ) {
    this._port = port;
    public void initialize()
    throws IOException {
    this._selector = SelectorProvider.provider().openSelector();
    this._selectableChannel = ServerSocketChannel.open();
         this._selectableChannel.configureBlocking(false);
         InetAddress lh = InetAddress.getLocalHost();
         InetSocketAddress isa = new InetSocketAddress(lh, this._port );
         this._selectableChannel.socket().bind(isa);
    public void finalize()
    throws IOException {
    this._selectableChannel.close();
    this._selector.close();
    public void acceptConnections()
    throws IOException {
    Selects a set of keys whose corresponding channels are ready for I/O
    operations. This method performs a non-blocking selection operation.
    If no channels have become selectable since the previous selection
    operation then this method immediately returns zero.
    Returns:
    The number of keys, possibly zero, whose ready-operation sets
    were updated by the selection operation
    do {
    SelectionKey acceptKey =
    this._selectableChannel.register( this._selector,
    SelectionKey.OP_ACCEPT );
    log.debug( "Acceptor loop..." );
    while (( this._keysAdded = acceptKey.selector().select()) > 0 ) {
    log.debug( "Selector returned "
    + this._keysAdded + " ready for IO operations" );
    Set readyKeys = this._selector.selectedKeys();
    Iterator i = readyKeys.iterator();
    while (i.hasNext()) {
    SelectionKey key = (SelectionKey)i.next();
    i.remove();
    if ( key.isAcceptable() ) {
    ServerSocketChannel nextReady =
    (ServerSocketChannel)key.channel();
    log.debug( "Processing selection key read="
    + key.isReadable() + " write=" + key.isWritable() +
    " accept=" + key.isAcceptable() );
    Socket s = nextReady.accept();
    s.getChannel().configureBlocking( false );
    SelectionKey readKey =
    s.getChannel().register( this._selector,
    SelectionKey.OP_READ );
    readKey.attach( s );
    else if ( key.isReadable() ) {
    SelectableChannel nextReady =
    (SelectableChannel) key.channel();
    log.debug( "Processing selection key read="
    + key.isReadable() + " write=" + key.isWritable() +
    " accept=" + key.isAcceptable() );
    Socket socket = (Socket) key.attachment();
    BufferedReader in = new BufferedReader(
    new InputStreamReader( socket.getInputStream() ));
    String line = null;
    if ( (line = in.readLine() ) != null )
    log.debug( line );
    log.debug( "End acceptor loop..." );
    } while ( false ); //FIXIT tim this should be false. justa test
    public static void main( String[] args ) {
    BasicConfigurator.configure();
    NBServer3 nbServer = new NBServer3();
    try {
    nbServer.initialize();
    } catch ( IOException e ) {
    e.printStackTrace();
    System.exit( -1 );
    try {
    nbServer.acceptConnections();
    catch ( IOException e ) {
    e.printStackTrace();
    log.error( e );

  • Writing Java Non-Blocking Socket Server for  Winsock Client

    Hi.
    Im a newbie to Sockets. I need to write a Non-Blocking Socket server (using java.nio) that accepts connection and reads the data sent by WinSock clients, and write them to another winsock client. Its quite intriguing. How do I do that? Is it possible?
    Thanks in advance
    Arun

    Well, in traditional 4.2 BSD sockets, you'd fill up a set of filedescriptors of connections (an array of bits usually), and push that in the read parameter of a call to 'select'. Select then blocks until at least one of the file descriptors become available for reading, or writing if you also made an fd_set full of file descriptors (but you can usually write freely to a socket, so there is not much use for that). Then you start finding out which of these file descriptors have actually become available for reading, and you pass those to a bunch of worker-threads. The advantage is that your set of worker-threads can be quite small, while your number of connections can still be quite large (unless, of course, everyone of your clients start talking all at once, but that is no different from the one-socket-one-thread-model that java.net.* forces upon you).
    In java, the 'select' call is replaced by a call to java.nio.channels.Selector.select(); and then the fishing out of the selected stuff comes from java.nio.channels.Selector.selectedKeys().
    To add a thingy to a selector, use (for example) java.nio.channel.ServerSocketChannel.register(Selector, ops, att);
    whereby the ops parameter is the kind of action you'd like to select this channel for; SelectionKey.OP_READ etc..
    The workerthread bit is also easy to write, but I leave that to you as an exercise.

  • Multiple non-blocking selectors in threads

    About networking in java and sockets i read alot. I know about the 2 implementations witk thread per client and non-blocking IO (usage of select()). I ran a few tests of my own and i could't decide. So I wrote a server that uses them both. The Ideea is to have no more than 100 clients per each selector and each selector runs in a thread. so when you have 4000 clients you actualy have 40 threads running each 100 clients:D
    However I'm stuck. I wrote this piece of code that has 2 objects one work thread with his own selector and a main thread with an accepting selector. The problem is that when I connect to it via telnet it only works when there is an even number of clients:(( when client nr 1 connects it blocks on channel.register(workSelector,SelectionKey.OP_READ);when client 2 gets connected it works:((
    HELP!!!
    here is the
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.charset.*;
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    //work thread with own selector
    class workThread implements Runnable{
         public int userCount=0;
         public int ID=0;
         private Charset charset;
         private CharsetEncoder encoder;
         private CharsetDecoder decoder;
         private ByteBuffer buffer;
         private ConcurrentHashMap userMap;
         public Selector workSelector = null;
         public void addClient(SelectableChannel channel, int ops) throws IOException{
              if (channel == null) return;
              //channel.configureBlocking(false);
              System.out.println("Channel was added in workSelector : "+channel);
              channel.register(workSelector,SelectionKey.OP_READ);
              System.out.println("Client was added in work selector : " + ID);
              userCount++;
              System.out.println("Client nr : "+userCount);
         public boolean find(String name){
              return true;
         public workThread() throws IOException{
              charset = Charset.forName("ISO-8859-1");
              encoder = charset.newEncoder();
              decoder     = charset.newDecoder();     
              buffer = ByteBuffer.allocate(256);
    //          System.out.println("S-a creat selectorul");
              workSelector = Selector.open();
              System.out.println("Selector open ");
         private void doRead(SelectionKey key) throws IOException{
              SocketChannel clientChannel = (SocketChannel)key.channel();
              buffer.clear();
              System.out.println("Speaking to client");
              if(clientChannel.read(buffer) == -1){
                   key.cancel();
                   clientChannel.close();
              }else{
                   buffer.flip();
                   String message = decoder.decode(buffer).toString();
                   System.out.println(message);
                   if(message.trim().equals(".")){
                        clientChannel.write(encoder.encode(CharBuffer.wrap("BYE")));
                        key.cancel();
                        clientChannel.close();
                   }else{
                        buffer.flip();
                        clientChannel.write(buffer);
         private void doWrite(SelectionKey key){
              System.out.println("WRITE!!!");
         public void run(){
              while(true){
                   try{
                   if(workSelector.select() > 0){
                        Set keys1 = workSelector.selectedKeys();
                        for(Iterator itr = keys1.iterator();itr.hasNext();){
                             SelectionKey key = (SelectionKey)itr.next();
                             itr.remove();
                             if(key.isReadable()) {doRead(key);}
                        //     if(key.isWritable()) {doWrite(key);}
              }catch(IOException e){
                   System.out.println("Error in workthread "+ID+" "+e);
    //main thread
    public class msselect implements Runnable{
         private ServerSocketChannel server;
         private ServerSocket sock;
         private Selector acceptSelector;
         private workThread wk;
         public static void main(String args[]){
              try{
              msselect x = new msselect("80.97.89.73",6500,5);
              new Thread(x).start();
              }catch(IOException ex){
                   System.out.println("Probleme"+ex);
         msselect(String host, int port, int numT) throws IOException{
              server = ServerSocketChannel.open();
              sock = server.socket();
              sock.bind(new InetSocketAddress(port));
              server.configureBlocking(false);
              acceptSelector = Selector.open();
              server.register(acceptSelector, SelectionKey.OP_ACCEPT);
    /*          for(int i=0;i<numT;i++){
                   wk[i] = new workThread();
                   wk.ID = i;
                   new Thread(wk[i]).start();
              wk = new workThread();
              wk.ID = 1;
              server.register(wk.workSelector, SelectionKey.OP_ACCEPT);
              new Thread(wk).start();
         public void run(){
              while(true){
                   try{
                   acceptSelector.select();
                   Set keys = acceptSelector.selectedKeys();
                   for(Iterator itr = keys.iterator();itr.hasNext();){
                        SelectionKey key = (SelectionKey)itr.next();
                        itr.remove();
                        if(key.isAcceptable()){
                             SocketChannel client = null;
                             client = server.accept();
                             client.configureBlocking(false);
                             System.out.println("Accepted "+client);
                             wk.addClient(client,SelectionKey.OP_READ);
              }catch(IOException e){
                   System.out.println("Main Thread error"+e);

    I compiled and ran your code.
    The call channel.register(...) should block while selector is blocked in workSelector.select(). The fact that the registration succeeds is that you registered the server channel with both the work selector and the acceptor selector. The work selector is returning from select() because of a new client connection is accepted and is a matter of thread scheduling that the client.register() succeeeds (but only sometimes).
    Possible solution:
    - don't register the server channel with the work selector;
    - probably call workSelector.wakeup() to make the client channel registration possible.

  • NIO SocketChannel non-blocking read

    Hello.
    I'm not sure a resembling message has already been posted in a forum. In such a case, thanks for redirecting to it.
    Goals :
    A selector is used by a main server thread to make accept and read operations non-blocking.
    When a connection is accepted, the newly created socket channel is configured as non-blocking, and a key is added to the selector with the OP_READ flag.
    When data are available on sockets, a new task (runnable) is created and submitted to a thread pool.
    When a thread is ready to process the request, a pre-allocated bytebuffer is used to read arriving data.
    The problem :
    When the bytebuffer capacity is less than the received bytes count, the read method on the socket channel interrupts the selector on the same selection key. In response to this event, a new task is initiated, interferring with the previous one.
    As expected according to my concurrency policy (ie. with a pool of threads), several requests are processed by parallel threads. To avoid unsafe accesses, i added a synchronized statement on the channel blocking lock, and it seems to works fine. But a better way should exist...
    Questions :
    Is this the expected behavior ?
    Is there any other way to read received data with a small buffer ?
    The full copy of the source code :
    import java.io.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.channels.spi.*;
    import java.nio.charset.*;
    import java.net.*;
    import java.util.*;
    import net.moon.threads.*;
    public class Nio1 {
         static class Request {
              boolean isCompleted = false;
              int inputs = 0;
              Set workers = new HashSet();
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              byte p = 0;
              boolean isCompleted() {
                   return isCompleted;
              void countInput() {
                   inputs++;
              void append(final ByteBuffer byteBuffer) {
                   if (isCompleted)
                        throw new IllegalStateException("Request is already completed");
                   workers.add(Thread.currentThread());
                   while (byteBuffer.hasRemaining()) {
                        byte b = byteBuffer.get();
                        baos.write(b);
                        if ((b == '\r') && (p == '\n'))
                             isCompleted = true;
                        p = b;
              int inputs() {
                   return inputs;
              Thread[] workers() {
                   return (Thread[]) workers.toArray(new Thread[0]);
              int size() {
                   return baos.size();
              byte[] getData() {
                   return baos.toByteArray();
              void reset() {
                   isCompleted = false;
                   inputs = 0;
                   baos.reset();
                   workers.clear();
         static private class RequestTask implements Runnable {
         private final static Charset charset = Charset.forName("US-ASCII");
              private final Server server;
              private final SelectionKey selectionKey;
              RequestTask(final Server server, final SelectionKey selectionKey) {
                   this.server = server;
                   this.selectionKey = selectionKey;
              public void run() {
                   log("*** Processing input...");
                   try {
                        SocketChannel channel = (SocketChannel) selectionKey.channel();
    synchronized(channel.blockingLock()) {
                        Request request = (Request) selectionKey.attachment();
                        request.countInput();
                        State state = getState();
                        log("Reading first...");
                        int c = channel.read(state.byteBuffer);
                        log("... Read first : " + c);
                        if (c > 0) {
                             for(;;) {
                                  state.byteBuffer.flip();
                             request.append(state.byteBuffer);
                                  state.byteBuffer.clear();
                                  if (c < state.byteBuffer.capacity()) break;
                                  log("Reading next...");
                                  c = channel.read(state.byteBuffer);
                                  log("... Read next : " + c);
                                  if (c <= 0) break;
                             if (request.isCompleted()) {
                                  log("Request completed : " + request.inputs());
                                  StringBuffer bodyBuffer = new StringBuffer();
                                  bodyBuffer.append("-----------------------------\r\n");
                                  bodyBuffer.append("Request processed in " + request.inputs() + " inputs\r\n");
                                  bodyBuffer.append("Request size is " + request.size() + " bytes\r\n");
                                  bodyBuffer.append("Participating workers :\r\n");
                                  Thread[] workers = request.workers();
                                  for (int i = 0; i < workers.length; i++)
                                       bodyBuffer.append(" * " + workers[i] + "\r\n");
                                  bodyBuffer.append("-----------------------------\r\n");
                                  StringBuffer headerBuffer = new StringBuffer();
                                  headerBuffer.append("HTTP/1.1 200 OK\r\n");
                                  headerBuffer.append("Server: NIO Server 1\r\n");
                                  headerBuffer.append("Content-Type: text/plain\r\n");
                                  headerBuffer.append("Content-Length: ").append(request.size() + bodyBuffer.length()).append("\r\n");
                                  headerBuffer.append("\r\n");
                             CharsetEncoder encoder = charset.newEncoder();
                                  channel.write(encoder.encode(CharBuffer.wrap(headerBuffer)));
                                  channel.write(encoder.encode(CharBuffer.wrap(bodyBuffer)));
                                  channel.write(ByteBuffer.wrap(request.getData()));
                                  request.reset();
                        if (c < 0) {
                             selectionKey.attach(null);
                             selectionKey.cancel();
                             log("!!! Connection terminated for channel " + channel);
                   catch(final Exception x) {
                        x.printStackTrace();
                   log("*** Request processed...");
              private State getState() {
                   State state = (State) server.taskManager.getCurrentWorkerState();
                   if (state == null) {
                        state = new State();
                        server.taskManager.setCurrentWorkerState(state);
                   else {
                        state.byteBuffer.clear();
                   return state;
              private void log(final String text) {
                   System.out.println(Thread.currentThread() + " : " + text);
              static class State {
                   ByteBuffer byteBuffer = ByteBuffer.allocateDirect(32);
         static private class Server implements Runnable {
              private final int port;
              private Thread worker;
              private FIFOTaskManager taskManager;
              Server(final int port) {
                   this.port = port;
                   worker = null;
              synchronized void start() throws Exception {
                   if (worker == null) {
                        log("Starting the server...");
                        taskManager = new FIFOTaskManager("Nio1Workers", 24);
                        worker = new Thread(this);
                        worker.start();
                        synchronized(worker) {
                             try {
                                  worker.wait();
                             catch(InterruptedException x) {
                        log("Server started !");
              public void run() {
                   try {
                        log("Server is starting...");
                        Selector selector = SelectorProvider.provider().openSelector();
                        log("Creating listener on port " + port);
                        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
                        serverSocketChannel.configureBlocking(false);
                        InetSocketAddress inetSocketAddress = new InetSocketAddress(port);
                        serverSocketChannel.socket().bind(inetSocketAddress);
                        SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
                        synchronized(worker) {
                             worker.notify();
                        while (selector.select() >= 0) {
                             Set readyKeys = selector.selectedKeys();
                             log("Keys are ready : " + readyKeys.size());
                             for (Iterator i = readyKeys.iterator(); i.hasNext(); ) {
                                  SelectionKey selectedKey = (SelectionKey) i.next();
                                  if (selectedKey.isAcceptable()) {
                                       ServerSocketChannel ssc = (ServerSocketChannel) selectedKey.channel();
                                       SocketChannel sc = ssc.accept();
                                       sc.configureBlocking(false);
                                       SelectionKey sk = sc.register(selector, SelectionKey.OP_READ);
                                       sk.attach(new Request());
                                       log("Connection accepted for channel " + sc);
                                  else if (selectedKey.isReadable()) {
                                       log("Key ready for input : " + selectedKey);
                                       taskManager.execute(new RequestTask(this, selectedKey));
                                  i.remove();
                             readyKeys = null;
                        log("Server loop interrupted !");
                   catch(Exception x) {
                        x.printStackTrace();
              private void log(final String text) {
                   System.out.println("SERVER: " + text);
         public static void main(final String[] args) throws Exception {
              Server server = new Server(9001);
              server.start();

    Thanks for the trick. I hope the code will be more readable than my sockets !
    import java.io.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.channels.spi.*;
    import java.nio.charset.*;
    import java.net.*;
    import java.util.*;
    import net.moon.threads.*;
    public class Nio1 {
         static class Request {
              boolean isCompleted = false;
              int inputs = 0;
              Set workers = new HashSet();
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              byte p = 0;
              boolean isCompleted() {
                   return isCompleted;
              void countInput() {
                   inputs++;
              void append(final ByteBuffer byteBuffer) {
                   if (isCompleted)
                        throw new IllegalStateException("Request is already completed");
                   workers.add(Thread.currentThread());
                   while (byteBuffer.hasRemaining()) {
                        byte b = byteBuffer.get();
                        baos.write(b);
                        if ((b == '\r') && (p == '\n'))
                             isCompleted = true;
                        p = b;
              int inputs() {
                   return inputs;
              Thread[] workers() {
                   return (Thread[]) workers.toArray(new Thread[0]);
              int size() {
                   return baos.size();
              byte[] getData() {
                   return baos.toByteArray();
              void reset() {
                   isCompleted = false;
                   inputs = 0;
                   baos.reset();
                   workers.clear();
         static private class RequestTask implements Runnable {
             private final static Charset charset = Charset.forName("US-ASCII");
              private final Server server;
              private final SelectionKey selectionKey;
              RequestTask(final Server server, final SelectionKey selectionKey) {
                   this.server = server;
                   this.selectionKey = selectionKey;
              public void run() {
                   log("*** Processing input...");
                   try {
                        SocketChannel channel = (SocketChannel) selectionKey.channel();
    synchronized(channel.blockingLock()) {
                        Request request = (Request) selectionKey.attachment();
                        request.countInput();
                        State state = getState();
                        log("Reading first...");
                        int c = channel.read(state.byteBuffer);
                        log("... Read first : " + c);
                        if (c > 0) {
                             for(;;) {
                                  state.byteBuffer.flip();
                                 request.append(state.byteBuffer);
                                  state.byteBuffer.clear();
                                  if (c < state.byteBuffer.capacity()) break;
                                  log("Reading next...");
                                  c = channel.read(state.byteBuffer);
                                  log("... Read next : " + c);
                                  if (c <= 0) break;
                             if (request.isCompleted()) {
                                  log("Request completed : " + request.inputs());
                                  StringBuffer bodyBuffer = new StringBuffer();
                                  bodyBuffer.append("-----------------------------\r\n");
                                  bodyBuffer.append("Request processed in " + request.inputs() + " inputs\r\n");
                                  bodyBuffer.append("Request size is " + request.size() + " bytes\r\n");
                                  bodyBuffer.append("Participating workers :\r\n");
                                  Thread[] workers = request.workers();
                                  for (int i = 0; i < workers.length; i++)
                                       bodyBuffer.append(" * " + workers[i] + "\r\n");
                                  bodyBuffer.append("-----------------------------\r\n");
                                  StringBuffer headerBuffer = new StringBuffer();
                                  headerBuffer.append("HTTP/1.1 200 OK\r\n");
                                  headerBuffer.append("Server: NIO Server 1\r\n");
                                  headerBuffer.append("Content-Type: text/plain\r\n");
                                  headerBuffer.append("Content-Length: ").append(request.size() + bodyBuffer.length()).append("\r\n");
                                  headerBuffer.append("\r\n");
                                 CharsetEncoder encoder = charset.newEncoder();
                                  channel.write(encoder.encode(CharBuffer.wrap(headerBuffer)));
                                  channel.write(encoder.encode(CharBuffer.wrap(bodyBuffer)));
                                  channel.write(ByteBuffer.wrap(request.getData()));
                                  request.reset();
                        if (c < 0) {
                             selectionKey.attach(null);
                             selectionKey.cancel();
                             log("!!! Connection terminated for channel " + channel);
                   catch(final Exception x) {
                        x.printStackTrace();
                   log("*** Request processed...");
              private State getState() {
                   State state = (State) server.taskManager.getCurrentWorkerState();
                   if (state == null) {
                        state = new State();
                        server.taskManager.setCurrentWorkerState(state);
                   else {
                        state.byteBuffer.clear();
                   return state;
              private void log(final String text) {
                   System.out.println(Thread.currentThread() + " : " + text);
              static class State {
                   ByteBuffer byteBuffer = ByteBuffer.allocateDirect(32);
         static private class Server implements Runnable {
              private final int port;
              private Thread worker;
              private FIFOTaskManager taskManager;
              Server(final int port) {
                   this.port = port;
                   worker = null;
              synchronized void start() throws Exception {
                   if (worker == null) {
                        log("Starting the server...");
                        taskManager = new FIFOTaskManager("Nio1Workers", 24);
                        worker = new Thread(this);
                        worker.start();
                        synchronized(worker) {
                             try {
                                  worker.wait();
                             catch(InterruptedException x) {
                        log("Server started !");
              public void run() {
                   try {
                        log("Server is starting...");
                        Selector selector = SelectorProvider.provider().openSelector();
                        log("Creating listener on port " + port);
                        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
                        serverSocketChannel.configureBlocking(false);
                        InetSocketAddress inetSocketAddress = new InetSocketAddress(port);
                        serverSocketChannel.socket().bind(inetSocketAddress);
                        SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
                        synchronized(worker) {
                             worker.notify();
                        while (selector.select() >= 0) {
                             Set readyKeys = selector.selectedKeys();
                             log("Keys are ready : " + readyKeys.size());
                             for (Iterator i = readyKeys.iterator(); i.hasNext(); ) {
                                  SelectionKey selectedKey = (SelectionKey) i.next();
                                  if (selectedKey.isAcceptable()) {
                                       ServerSocketChannel ssc = (ServerSocketChannel) selectedKey.channel();
                                       SocketChannel sc = ssc.accept();
                                       sc.configureBlocking(false);
                                       SelectionKey sk = sc.register(selector, SelectionKey.OP_READ);
                                       sk.attach(new Request());
                                       log("Connection accepted for channel " + sc);
                                  else if (selectedKey.isReadable()) {
                                       log("Key ready for input : " + selectedKey);
                                       taskManager.execute(new RequestTask(this, selectedKey));
                                  i.remove();
                             readyKeys = null;
                        log("Server loop interrupted !");
                   catch(Exception x) {
                        x.printStackTrace();
              private void log(final String text) {
                   System.out.println("SERVER: " + text);
         public static void main(final String[] args) throws Exception {
              Server server = new Server(9001);
              server.start();
    }

  • FileChannel.transferTo() using non-blocking SocketChannel

    I'm looking to use FileChannel.transfer(From/To) for performing file transfers over a network. On the uploading side I find that even though I set the SocketChannel to non-blocking mode, the loop manages to send files as large as 30MB in only a single transferTo() invocation. What I'm hoping for is to have a series of partial writes so that I might generate progress notifications, which does occur on the downloading side with transferFrom(). I don't think a file that large should be transferred in one pass so I'm thinking that this is caused by either some internal buffer allocation issue or a goof-up on my part.
    Thanks in advance for any input and here's the uploading code:
    public void upload( String fileName ) {
    FileInputStream fileStrm = null;
    FileChannel fileChan = null;
    FileLock fileLock = null;
    SocketChannel sockChan = null;
    Selector selector = null;
    try {
    // Lock the source file.
    file = new File( fileName );
    fileStrm = new FileInputStream( file );
    fileChan = fileStrm.getChannel();
    fileLock = fileChan.lock( 0L, Long.MAX_VALUE, true );
    // Open a server socket bound to an arbitrary port.
    servChan = ServerSocketChannel.open();
    servChan.socket().bind( new InetSocketAddress( 0 ) );
    // Wait for a single connection and close the server socket.
    sockChan = servChan.accept();
    servChan.close();
    sockChan.configureBlocking( false );
    selector = Selector.open();
    SelectionKey selectorKey = sockChan.register( selector, SelectionKey.OP_WRITE );
    // Loop until transfer has completed.
    int fileSize = ( int ) file.length();
    int sizeLeft = fileSize;
    while ( sizeLeft > 0 ) {
    // Wait for data to read, then transfer it.
    if ( selector.select() == 1 && selectorKey.isWritable() ) {
    sizeLeft -= ( int ) fileChan.transferTo( fileSize - sizeLeft, sizeLeft, sockChan );
    // Generate a progress notification here such as:
    // monitor.bytesTransferred( fileSize - sizeLeft );
    catch ( IOException ex ) {
    ex.printStackTrace();
    finally {
    try {
    // Cleanup.
    if ( selector != null )
    selector.close();
    if ( sockChan != null )
    sockChan.close();
    if ( fileLock != null )
    fileLock.release();
    if ( fileChan != null )
    fileChan.close();
    if ( fileStrm != null )
    fileStrm.close();
    catch ( IOException ex ) {
    ex.printStackTrace();
    -Edwin

    Actually, the sending process appears way ahead of the receiving one, where the send seems to finish in a blink while the receive takes several seconds to complete. In other words, the transferTo() completes in one loop, while the transferFrom() performs many with delays in between. I'd guess all that data is sitting in some large outbound buffer at the sender, which would explain why it seems to finish too quickly. If I split the send into smaller chunks, the two sides run quite nearly at the same pace as expected.
    The receiver already sleeps by way of a select() against a non-blocking SocketChannel, so I'll try reducing the buffer sizes as you suggest.

  • Are the experts wrong about non-blocking SocketChannels?

    Everyone says to use the new SocketChannel and Selector for "highly scalable" server applications. So I ran a couple of tests using non-blocking (via Selector) and thread-per-connection SocketChannels.
    The Selector version consumes 8x more cpu than the thread-per-connecton version!
    Using JDK 1.4.1 FCS on Win2K, with 1000 socket connections each sending 1k bytes per second, the Selector version was consuming 40% cpu with 10 threads; the thread-per-connection version (using blocking SocketChannels) was only consuming about 5% cpu with 1009 threads.
    So, are the experts wrong? Is there a performance problem when number of SocketChannels exceed a certain threshold?
    For anyone interested, here's the source code:
    Non-Blocking Server using Selector
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import java.nio.charset.CharsetEncoder;
    import java.nio.channels.FileChannel;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    public class Server4 implements Runnable
    private static int port = 80;
    public static void main(String args[]) throws Exception
    Server4 server = new Server4();
    Thread thread = new Thread(server);
    thread.setDaemon(true);
    thread.start();
    thread.join();
    public Server4() throws IOException
    ServerSocketChannel server = ServerSocketChannel.open();
    InetSocketAddress isa = new InetSocketAddress(port);
    server.configureBlocking(false);
    server.socket().bind(isa);
    m_selector = Selector.open();
    server.register(m_selector, SelectionKey.OP_ACCEPT);
    Charset utf8 = Charset.forName("UTF-8");
    m_decoder = utf8.newDecoder();
    m_encoder = utf8.newEncoder();
    public void run()
    int count = 0;
    try
    ByteBuffer buffer = ByteBuffer.allocateDirect(2048);
    //FileOutputStream fos = new FileOutputStream("server4.dat");
    //FileChannel fc = fos.getChannel();
    while (m_selector.select() > 0)
    Set keys = m_selector.selectedKeys();
    for (Iterator itr = keys.iterator(); itr.hasNext(); )
    SelectionKey key = (SelectionKey) itr.next();
    itr.remove();
    if (key.isAcceptable())
    System.out.println("accept: " + (++count));
    ServerSocketChannel server
    = (ServerSocketChannel) key.channel();
    SocketChannel channel = server.accept();
    channel.configureBlocking(false);
    channel.register(m_selector, SelectionKey.OP_READ);
    else
    SocketChannel channel = null;
    try
    if (key.isReadable())
    channel = (SocketChannel) key.channel();
    int bytes = channel.read(buffer);
    if (bytes <= 0) // Linux does not throw IOException
    channel.close(); // will also cancel key
    System.out.println("connection closed " + count);
    else
    buffer.flip();
    //fc.write(buffer);
    buffer.clear();
    catch (IOException ioe) // connection closed by client
    System.out.println("readable: " + ioe.getMessage());
    sm_logger.log(Level.INFO, ioe.getMessage(), ioe);
    Throwable cause = ioe.getCause();
    if (cause != null)
    System.out.println("cause: "
    + cause.getClass().getName()
    + ": " + cause.getMessage());
    channel.close(); // will also cancel key
    --count;
    catch (IOException e)
    System.out.println("run: " + e.getMessage());
    sm_logger.log(Level.SEVERE, e.getMessage(), e);
    catch (Exception e)
    System.out.println("run: " + e.getMessage());
    sm_logger.log(Level.SEVERE, e.getMessage(), e);
    private Selector m_selector;
    private CharsetDecoder m_decoder;
    private CharsetEncoder m_encoder;
    private static Logger sm_logger = Logger.getLogger("Server");
    Thread-Per-Connection Server
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import java.nio.charset.CharsetEncoder;
    import java.nio.channels.FileChannel;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    public class MultiThreadServer implements Runnable
    private static int port = 80;
    public static void main(String[] args) throws Exception
    ServerSocketChannel server = ServerSocketChannel.open();
    InetSocketAddress isa = new InetSocketAddress(port);
    server.socket().bind(isa);
    int count = 0;
    while (true)
    SocketChannel channel = server.accept();
    System.out.println("accept: " + (++count));
    MultiThreadServer worker = new MultiThreadServer(channel);
    Thread thread = new Thread(worker);
    thread.setDaemon(true);
    thread.start();
    public MultiThreadServer(SocketChannel channel) throws IOException
    m_channel = channel;
    public void run()
    ByteBuffer buffer = ByteBuffer.allocateDirect(2048);
    int bytes = 0;
    try
    while ((bytes = m_channel.read(buffer)) > 0)
    buffer.flip();
    // process buffer
    buffer.clear();
    System.out.println("connection closed");
    m_channel.close();
    catch (IOException e)
    System.out.println("run: " + e.getMessage());
    sm_logger.log(Level.SEVERE, e.getMessage(), e);
    catch (Exception e)
    System.out.println("run: " + e.getMessage());
    sm_logger.log(Level.SEVERE, e.getMessage(), e);
    private SocketChannel m_channel;
    private static Logger sm_logger = Logger.getLogger("MultiThreadServer");
    Client
    import java.io.*;
    import java.net.*;
    import java.nio.*;
    import java.nio.channels.*;
    import java.nio.charset.*;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.Set;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    public class MultiClient implements Runnable
    public static void main(String[] args) throws Exception
    if (args.length < 1)
    System.out.println("usage: java MultiClient number [host]");
    System.exit(1);
    int number = Integer.parseInt(args[0]);
    String host = (args.length == 2) ? args[1] : "localhost" ;
    Thread[] threads = new Thread [number];
    InetSocketAddress address = new InetSocketAddress(host, 80);
    for (int i = 0; i < number; i++)
    MultiClient client = new MultiClient(address, Integer.toString(i));
    threads[i] = new Thread(client);
    threads.setDaemon(true);
    for (int i = 0; i < number; i++)
    threads[i].start();
    for (int i = 0; i < number; i++)
    threads[i].join();
    public MultiClient(InetSocketAddress address, String id)
    throws InterruptedException, IOException
    m_id = id;
    Charset charset = Charset.forName("UTF-8");
    m_decoder = charset.newDecoder();
    m_encoder = charset.newEncoder();
    m_channel = SocketChannel.open();
    m_channel.connect(address);
    if (id.equals("0"))
    Socket socket = m_channel.socket();
    System.out.println("SO_SNDBUF=" + socket.getSendBufferSize()
    + ",SO_TIMEOUT=" + socket.getSoTimeout()
    + ",SO_KEEPALIVE=" + socket.getKeepAlive());
    byte[] buf = new byte [1024]; // bufsize = 1K
    Arrays.fill(buf, (byte) m_id.charAt(0));
    m_buffer = ByteBuffer.allocateDirect(1024);
    m_buffer.put(buf);
    m_buffer.flip();
    Thread.currentThread().sleep(50L);
    public void run()
    System.out.print(m_id);
    try
    while (true)
    m_channel.write(m_buffer);
    m_buffer.rewind();
    Thread.currentThread().sleep(1000L);
    catch (IOException ioe)
    ioe.printStackTrace();
    catch (InterruptedException ie)
    System.err.println(ie.toString());
    private String m_id;
    private CharsetEncoder m_encoder;
    private CharsetDecoder m_decoder;
    private SocketChannel m_channel;
    private ByteBuffer m_buffer;

    {This is a crosspost. I posted this earlier today at http://forum.java.sun.com/thread.jsp?forum=4&thread=319822 before I stumbled on a search phrase that located this older thread.
    All follow-ups should be on haam's thread instead of mine. The important point below is that NIO select() behavior (vs. threading IO)  is [b]worse under Windows but better under Solaris. This seems fundamentally broken. }
    My company sells a scalable multi-user server platform built on Java 2.
    It runs under Java 1.3.1 (and 1.4.0 windows) using multiple threads for communications, and 1.4.x (unix) using NIO. We were happy to see that 1.4.1 (windows) fixed the problem drastically limiting the number of selectable ports. :-)
    The bad news is that whatever the VM is doing "under the sheets" to fix the problem seems to perform very poorly in terms of CPU:
    I compared connecting 500 simulated users to a Solaris 8 and a Win2K box. These users were in 25 chat rooms, each sending a chat message every 30 seconds. (There was plenty of memory on each machine. There was no swapping in either case. Clock/CPU type doesn't matter as this isn't about comparing a machine to a machine, but different load characteristics -within- a machine environment.)
                    Threaded IO      NIO/Select
    Solaris 1.4.1     20-30%           15- 20%
    Windows 1.4.1     40-50%           95-100%Numbers are % of CPU as reported by 'top' and the Win2K task manager.
    Both platforms showed the expected significant improvement in memory usage when moving from standard threaded IO to NIO.
    Strangely, the Windows implementation of the VM showed a significant (and unexpected) degradation of NIO performance vs. the threaded model, whereas the Solaris VM behaved as expected: NIO outperformed threaded IO.
    Our best guess is that the Selector fix in 1.4.1 is implemented in some cpu-intensive way; perhaps polling. As a result, we still can't use NIO for Wintel boxes running our server. :-( To us, Selector
    is still broken.
    Has anyone else seen results like this? Have we missed some configuration parameter that will fix this?
    I thought the big upside of using select() was supposed to be performance. :-P
    F. Randall Farmer
    State Software, Inc.
    http://www.statesoftware.com

  • Non blocking jDialog & return values

    Hi,
    I have (at the center of this problem) 3 classes. A controller class, and two jDialog windows.
    The controller initiates the first jDialog window (a main menu window). When the use clicks on a button the second jDialog window opens (a search window).
    How do I start the jDialog windows without the controller blocking on the show() calls?

    solved the non-blocking problem now have another lol!
    the method in the controller now does not block and the search dialog is displayed fine.
    It displays a list of results and the use double clicks on a result to display the details. I am using a jTable to display the results. The table has a mouse click listener that detects the double click. How do i notify the my controller class that the use has selected a result?
    If this is an easy problem, accept my apologies, I am relatively new to java...

  • Non-blocking SocketChannel and close - huh?

    It looks like closing a socketchannel that is in non-blocking mode can result in a dead drop of the connection, with some bytes that have already been sent and accepted (as in, 'consumed' from the buffer) being completely dropped.
    In fact, I'm generally confused: Actual C non-blocking code has a similar setup for 'close' as you can see in SocketChannel's OP_CONNECT behaviour - just because you want to connect the socket doesn't mean it magically happends without blocking. Wait for a ready flag, then try again.
    It should work the same way with close (you try to close, but it may not be possible without blocking).
    Is this a huge gaping bug that no one quite figured out just yet, or did I miss something? I loathe to turn on linger, as that's just a crapshoot (you never know if it actually gets through. You could run into funny surprises once the server gets a bit busy. I'd rather not) and tends to cause massive leaks on linux, at least according to some google searches.
    There seems to be slightly better performance (in that I have always received all data sofar) if I close the socket instead of the channel (socketChannel.socket().close() instead of socketChannel.close()) - but this has been a random attempt at 'making it work', and I can't find any documentation that backs up that this will DEFINITELY not lose any information without letting me know somehow. That still sounds impossible with this approach.

    Actual C non-blocking code has a similar setup for
    'close' as you can see in SocketChannel's
    OP_CONNECT behaviour ...No it doesn't. I don't know what you mean by this.
    Closing a socket is asynchronous, but it shouldn't lose any data - if the data can be delivered it will be, followed by the FIN. You don't know when it is delivered, and you don't get to hear about any errors such as an RST coming from the other end, say if it decided to close before reading all the data, or if some intermediate router hung you up.
    I'm wondering if you are really dealing with all the short write and zero length write possibilities, i.e. whether the data isn't really still in your output buffer. Don't wish to teach you to suck eggs but there are some subtleties here.
    Setting a positive linger timeout doesn't really help because Java doesn't tell you if the timeout expired. (I only asked for this about four years ago). You get to wait while any pending data is delivered, but you still have to guess about whether it all went or the timeout expired, and the behaviour after the timeout expires is platform-dependent: some (Windows) issue an RST, others (Unix) keep trying.
    Blocking or non-blocking mode shouldn't make any difference to this (except that Linux will block on a positive linger timeout even in non-blocking mode, which is wrong), and whether you close the channel or the socket is immaterial as one calls the other anyway.
    The reason why OP_CONNECT is different in blocking/non-blocking modes is that in blocking mode it won't return until the SYN-ACK is received, while in non-blocking mode it just sends the SYN and relies on you calling connect() again (at the C level) to collect the SYN-ACK, or not - this is what finishConnect() tells you.
    tends to cause massive leaks on linux, at least
    according to some google searchesIt can't, unless you are referring to the Helix client thing, which appears to be just a badly designed C++ class library with, for some reason, its own linger implementation outside the kernel.

  • How to generate non-blocking commands to a serial device

    I have a serial device which accepts non-blocking commands. This is, if you send a command that takes 1 minute, while this happens, you can send more commands and they will be executed. Once a command is done, it sends back a code that relates to that command, so you know it is finished.
    I have a VI which tries to communicate with this serial device (see attachment). It does work, but it blocks the execution until a command is finished. So I can send commands one by one, but not in parallel, or in a delayed non-block way. The problem is the while loop which waits until the device outputs something.
    I need to do something similar, but non blocking. The VI should be able to send several commands while others are executed.
    This subVI is controlled from a main VI, which is just a State Machine with a few states, where each state is some action which is sent to this subVI, and then to the serial device.
    Attachments:
    blocking_vi.png ‏27 KB

    Use another loop that does nothing but read from the serial port.  Report the data to whoever needs it with a Queue.
    There are only two ways to tell somebody thanks: Kudos and Marked Solutions
    Unofficial Forum Rules and Guidelines

Maybe you are looking for

  • Greetings.  I need to know what to do if a formerly recognized external drive is no longer recognized by my iMac.

    Greetings.  I could use some advice here. I bought a WD external hard drive to back-up some files on my old iMac, but I reformatted it & set it up on my new iMac. After I backed up the files I wanted, I hooked the external drive to the new iMac, but

  • HP LaserJet CP1525nw makes terrible swealing noise when printing

    Product:  HP LaserJet CP1525nw OS:  Windows 7 Error Msg:  none The product makes a loud squealing noise when printing.  It also leaves streak marks on envelopes. Product was purchased Dec. 21, 2010, so is only a little over one year old, but is out o

  • Monitoring HD editing

    I am just starting to modify my workflow hardware to accommodate HD post production. I've been doing SD using a Canopus ADVC 100 to monitor footage while I'm editing in real-time. The ADVC 100 inputs from my Mac Pro via FW400 and outputs via standard

  • UPK preview topic not displaying after being published

    After preview topic loads, it will not display. We have already disabled popup blocker. Any help would be appreciated..

  • Www I guess this is correct?

    hi , i just went to my hosting site after adding my address details in .Mac. i went into my hosting site then clicked edit DNS and it gives me options for DNS or CNAME ,I checked CNAME and added web.mac.com as advised on .Mac page when i inputting do