Non-blocking connection on a SocketChannel?

I'm trying out the non-blocking connection of a SocketChannel. So I wrote the following test code and supply a list of IPs (both good and bad IPs). But disregard the IPs I always get the result of a channel being in connection pending state (even for some bogus IPs). Any help will be great.
public class ConnectTest
    public static void main(String[] args) throws
Exception
        List<SocketChannel> channels = new ArrayList<SocketChannel>();
        for ( String s: args )
            SocketChannel channel = SocketChannel.open();
            channel.configureBlocking(false);
            channels.add(channel);        
            InetSocketAddress remote = new InetSocketAddress(s, 80);
            channel.connect(remote);
        System.out.println("wait for timeout...");
        Thread.sleep(10000);
        for ( SocketChannel c : channels )
            if ( c.isConnected() )
                System.out.println(c.socket().getInetAddress() + " connected ");
            else if ( c.isConnectionPending() )
                System.out.println(c.socket().getInetAddress() + " connection pending ");               
            else
                System.out.println(c.socket().getInetAddress() + " timeout ");
            c.close();
}

Forget the sleep: use a Selector, selecting on OP_CONNECT. When you get it, call SocketChannel.finishConnect() for the channel(s) selected. If that method returns 'true', the connection is complete. If it returns 'false', the connection is still pending (and in fact OP_CONNECT should not have fired); if it throws an exception, the connection attempt has failed.
If the connection is complete you must also deregister it for OP_CONNECT before registering it for OP_READ or OP_WRITE.

Similar Messages

  • JDK 1.4 nio non-blocking connects don't finish

    I am working with the Linux version of JDK1.4, doing some testing of the
    non-blocking capability. The few tests that I have done have shown some
    strange results:
    - When opening a non-blocking connection to a server which has an
    announcement banner, say such as POP which gives something like:
    +OK pop3 server ready
    then connection seems to be OK and proceed through to completion.
    - When opening a non-blocking connection to a server which is silent, and
    expects me to start the conversation, such as contacting an HTTP server,
    then the Selector.select() never returns to allow me to finish the
    connection.
    Below is a test program which illustrates the problem for me.
    It attempts to open a non-blocking connection to www.yahoo.com on port 80.
    It then drops into a Selector.select() where I am waiting for the chance to
    catch the SelectionKey.OP_CONNECT event and finish connecting, and then send
    a simple HTTP GET request down the wire. That OP_CONNECT event
    never seems to arrive though, and I remain stuck in the select().
    'netstat -na' shows that I am in a connection established state.
    Any insight appreciated,
    -Steve M [email protected]
    ------------------>8 cut here 8<-----------------------
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import java.nio.*;
    import java.nio.channels.*;
    public class NoWorkee
    public static String GET_REQUEST = "GET / HTTP/1.0\r\n\r\n";
        static class Context
            String host;
            int    port;
            ByteBuffer request;
            public Context (String h, int p, ByteBuffer r)
            {host=h; port=p; request=r;}
    Selector sel = null;
    boolean keepGoing = true;
    public NoWorkee()
        throws IOException
        sel = Selector.open();
    public void add(String host, int port)
        throws IOException
        int ops = SelectionKey.OP_CONNECT;
        // create non-blocking socket, and initiate connect operation
        SocketChannel sc = SocketChannel.open();
        sc.configureBlocking(false);
        sc.connect(new InetSocketAddress(InetAddress.getByName(host), port));
        SelectionKey sk;
        try
            sk = sc.register(sel, ops);
            System.out.println ( "sc.register looks good connected=" +
                sc.isConnected() + ", isConnectionPending=" +
                sc.isConnectionPending());
            sk.attach(new Context(host, port, ByteBuffer.wrap(GET_REQUEST.getBytes())));
        catch (IOException x)
            x.printStackTrace();
            sc.close();
    public void run()
        throws IOException
        keepGoing = true;
        System.out.println ( "Selecting " + sel.keys().size() + " SelectKeys");
        while (keepGoing)
            final long before = System.currentTimeMillis();
            final int numReady = sel.select();
            //final int numReady = sel.select(1000);
            final long after = System.currentTimeMillis();
            System.out.println ( "Blocked " + (after-before) + " ms, numReady=" + numReady);
            if (numReady > 0)
                Set readyKeys = sel.selectedKeys();
                System.out.println ( "Selected keys size " + readyKeys.size());
                for (Iterator it = readyKeys.iterator(); it.hasNext();)
                    SelectionKey sk = (SelectionKey)it.next();
                    SocketChannel sockChan = (SocketChannel)sk.channel();
                    Context ctx = (Context)sk.attachment();
                    System.out.println ( "Servicing host " + ctx.host + " port "
                                 ctx.port);
    System.out.println ( "1");
                    if (sk.isConnectable())
                        if (sockChan.finishConnect())
                            System.out.println ( "Finished connecting success "
    + sockChan);
                            int ops = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
                            sk.interestOps (ops);
                        else
                            System.out.println ( "Could not finishConnect for "
                                sockChan);
                            sk.cancel();
                            sockChan.close();
    System.out.println ( "2");
                    if (sk.isAcceptable())
                        System.out.println ( "in sk.isAcceptable() block");
    System.out.println ( "3");
                    if (sk.isReadable())
                        System.out.println ( "in sk.isReadable() block");
                        byte rawBuff[] = new byte[32 * 1024];
                        ByteBuffer buff = ByteBuffer.wrap(rawBuff);
                        int numRead = -1;
                        while (0 < (numRead = sockChan.read(buff)))
                            System.out.println ( "numRead = " + numRead);
                            for (int i = 0; i < numRead; i++)
                                System.out.print((char)rawBuff);
    System.out.println ( "numRead = " + numRead);
    System.out.println ( "4");
    if (sk.isWritable())
    System.out.println ( "in sk.isReadable() block");
    int numWritten = -1;
    if (null != ctx.request)
    numWritten = sockChan.write(ctx.request);
    if (!ctx.request.hasRemaining())
    sk.interestOps(sk.interestOps() &
    ~SelectionKey.OP_WRITE);
    System.out.println ( "numWritten = " + numWritten);
    //else
    // service timeouts
    public static void main (String arg[])
    try
    NoWorkee bla = new NoWorkee();
    bla.add ("www.yahoo.com", 80);
    bla.run();
    catch (Exception e)
    e.printStackTrace();
    ------------------>8 cut here 8<-----------------------

    Just for the benefit of anyone who might be seeing the same problem, it looks like bug 4457776 accurately describes the problem that I was having above.
    I am downloading j2sdk-1_4_0-beta2-linux-i386-rpm.bin to see if that fixed it.
    Reference:
    http://developer.java.sun.com/developer/bugParade/bugs/4457776.html

  • Using OCIBindDynamic with non-blocking connections

    I need to use an OCI array interface for execute statements more than once per one request to server.
    When I have called stored procedure or function in the non-blocking connection context using OCIBindDynamic for parameter binding, application have been crashed at random time.
    I don't have any problems using default (blocking) mode.
    Environment:
    Oracle 8.1.7 release 3 for Windows
    MS Visual C++ 6.0 compiler
    Could anybody help me ?

    It's always possible in any read that the number of bytes read is less than the number of bytes requested. You need to keep reading until you have got everything you expected, and cope with every possible error condition on each iteration.
    EJP

  • Using non blocking connect() call for SCTP sockets in Solaris10

    Hi,
    I have a problem with non blocking connect call on SCTP socket.
    I am using the sctp stack support in Solaris10.
    When the connect is successful, I can get the pollout event on the socket.
    But there is no event observed when the peer does not exist. In other words, I could not get the pollout event on connection failure. This logic works fine with TCP sockets on both Solaris and Suse10.
    I am working with SCTP one-to-one style sockets.
    Is there any way to handle this issue?
    Do I need to load any patch to resolve this issue?
    It will be great if I get a solution in this regard.
    Thanks in advance.
    Best Regards,
    Bipin.

    There are at least two problems here.
    A. In the receiver you should test for -1 from the read() immediately, rather than continue with the loop and try to write -1 bytes to the file.
    B. In the sender you are ignoring the return value of client.write(), which can be anything from 0 to the buffer length. If you get 0 you should wait for another OP_WRITE to trigger; if you get a 'short write' you need to retry it until you've got nothing left to write from the current buffer, before you read any more data. This is where the data is vanishing.

  • Non-blocking Vectored read from SocketChannel fails

    Hi.
    Please look at the code example:
    ByteBuffer tmp1 = ByteBuffer.allocate(500);
    ByteBuffer tmp2 = ByteBuffer.allocate(500);
    ByteBuffer[] tmp = {tmp1, tmp2};
    while ((count = socketChannel.read(tmp)) > 0) {
    + "bytes.");
    When I run this code, (using non-blocking socket channel), the first buffer is read ok, but on the second round of the while loop, I get an IOException, saying: "a non blocking socket operation could not be completed immediately".
    If I put 'tmp1' instead of 'tmp' in the read(), (i.e - use a normal buffer), the read successfully finishes.
    Why?
    I found nothing in the documentation, and in the 'Java NIO' book (Ron Hitchens).
    Help?
    Thanks.

    Please ignore the + "bytes."); inside the while.

  • Non-Blocking Server closes his socketChannels on his own (10 dukes)

    Hi,
    I have created a server using the new nio package. Clients can connect and disconnect as they wish : the client has a GUI with a button "connect" and a button "disconnect". When the client engages a new connection with the server, the ServerSocketChannel returns a new SocketChannel. I keep the socket connection alive until the client clicks on the "disconnect" button : it sends -1 to the server (socket.close() on the client), the SocketChannel reads it, and I close the SocketChannel.
    This works perfect with multiple clients, until... I wait 30mn...
    Exemple :
    1) I connect 1 PC to the server.
    2) The socket connection with this client is alive. On the server, I will name the SocketChannel that manages this connection "socketChannel1".
    3) I wait 30mn, and I connect an other PC to the server.
    4) Then, just at this very moment, "socketChannel1" receives -1 ==> my connection is closed as I haven't asked for anything.
    NB : If I don't wait the 30mn (approximatively), everything is ok. The "socketChannel1" doesn't disconnect ever.
    NB2 : If I connect my 2 clients to the server, I wait 30mn, and then I disconnect one of the clients, then the other automatically disconnects (socketChannel receives -1).
    NB3 : If there is 2, 3 or more clients... I wait 30mn, and one of the clients disconnect ==> everybody disconnects.
    I wonder if there is a timeout or something for the SocketChannel class, or the Select class... Seems strange... Possible?
    I would really appreciate any help. I'm on this problem for days, and I still don't see. If ever you had any idea...
    Thank you very much.
    If you want more precisions, code, or something... You can ask. Thank you.

    I have perhaps an idea of what is going on...
    On my server, when a client connects, he writes on the socketChannels of the other connected clients (to notify them the connection). I don't use the "key.isWritable()" state that is in the while of the "selector.select()". Perhaps is that an error. I write on all the socketChannels in the "if (key.isReadable())" :
    if (key.isReadable()) {
         for (int i=0; i<openedSocketChannelNumber; i++) {
              SocketChannel channel = (SocketChannel) vector.get(i);
              channel.write("connect"); // I made it short here...
    perhaps it isn't supported... I'll try to use the "if (key.isWritable) { }" to write on the other socketChannels.
    If any idea... Still and always welcome.

  • Non-Blocking SocketChannel read give Connection timed out

    Hi,
    My program is using Non-Block NIO SocketChannel for both Server and Client sides. However, if the connection between server and client has been idle for a while, when the client try to communicate with server, it gets blocked for a while (15 minutes) and then receives the following exception:
    java.io.IOException: Connection timed out
         at sun.nio.ch.FileDispatcher.read0(Native Method)
         at sun.nio.ch.SocketDispatcher.read(Unknown Source)
         at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
         at sun.nio.ch.IOUtil.read(Unknown Source)
         at sun.nio.ch.SocketChannelImpl.read(Unknown Source)
    How can this be since the read is in Non-Blocking mode? Also, is there anyway to determine the timeout without being blocked?

    This would mean that you are trying to read from the socket without having properly completed the connection, which timed out. I would say you are connecting in non-blocking mode but not calling finishConnect() when you get OP_CONNECT.

  • NIO: Strange problem when using ByteBuffer with non-blocking SocketChannel

    Hi,
    I have a server that uses multiplexed, non-blocking I/O with java.nio. When a client connects, the server waits for the message: <system cmd="knock"/>, returns a message and disconnects the client. The clients are shortly serviced in less than a second.
    But the server newer receive anything from about 20% of the clients - even though it is sent. Or with other words: it is received and the data is contained in the ByteBuffer - SocketChannel.read(ByteBuffer) - but a call to ByteBuffer.remaing() returns 0 !!
    ByteBuffer receiveBuf = ByteBuffer.allocate(65536);
    receiveBuf.clear(); // the code is elsewhere used for longer living clients
    int readBytes = channel.read(receiveBuf);
    receiveBuf.flip();
    StringBuffer sb = new StringBuffer();
    System.out.println(" * Remaining: "+receiveBuf.remaining()); // writes: ' * Remaining: 0'
    System.out.println(" * Received: "+new String(receiveBuf.array())); // writes: ' * Received: <system cmd="knock"/>'
    while(receiveBuf.remaining() >= 2) {
      byte b = receiveBuf.get();
      sb.append((char)b);
    System.out.println(" * sb content: "+sb.toString()); // writes: ' * sb content: 'The ByteBuffer clearly receives the correct data, but the ByteBuffer.remaining() returns 0 and therefore the StringBuffer will never have any content.
    The problem seems to occur randomly and for about 20% of the clients (simulated from the same computer and therefore has the same bandwidth and so on).
    Anyone knows what is going on, and how to solve the problem !?

    It's always possible in any read that the number of bytes read is less than the number of bytes requested. You need to keep reading until you have got everything you expected, and cope with every possible error condition on each iteration.
    EJP

  • 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.

  • 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 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?

  • Java.io.IOException: Connection timed out while using non-blocking NIO

    Hi,
    I am using non-blocking NIO on jdk 1.6 to transfer files between two processes. The problem is that the sender thread times out on the write call even though it's in non-blocking mode. It doesn't make sense. The receiver on the other end is running fine, and even tries to read from the socket after the sender drops the connection, and throws a Connection reset by peer exception. I should mention that the receiver is sometimes busy doing other stuff, and may be a second or two late in issuing the read call. But if I understand correctly, default TCP timeout is about 2 minutes, so there's no reason why it should timeout in a second or two. I'd appreciate it if anyone has any insight.
    Thanks!

    No I have definitely completed the connection since I it happens a while after the transfer has actually started and part of the file has already been transferred. Oh btw, I should mention that it doesn't always happen. It's intermittent. And it's not a network issue since iperf tests between the two nodes show nothing unusual.

  • 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

Maybe you are looking for

  • Nokia N95 v31.0.017 Bugs- Demanding a new firmware...

    Hello guys, I have recently upgrade my firmware from a nice v30 to v31 with hope of improvement in many things. But I end up very regretful after. My phone is no longer do what V30 allowed me to do. For example:                 Taking Picture using t

  • How to open pdfs directly in acrobat reader client side without using browser

    When I sent a request to the pdf through servlet the requested pdf is coming in a browser , but I want it to open in acrobat reader only . Is it possible ?

  • Volume icon is disfigured. Any solutions to this problem?

    I logged into my macbook pro like I do everyday and when I clicked on the volume key the volume icon appeared to have weird lines on both the top and the bottom. It has happened to one of my friends a few months ago and she never knew how to fix it a

  • Why does this expression not work as I'd hoped?

    I have a Black Solid 3 with a CC Particle World placed within it. I have some particles set up to run at 0.01 velocity outward from the center of my composition. I've put the following expression on the Velocity setting: value = thisComp.layer("Audio

  • Unable to edit information

    I just purchased a notebook with Vista 64bit. I have found that I am unable to edit info with Vista but am able to with XP on my desktop. I have not found any threads that helped. If anyone knows of a solution short of not using Vista I would appreci