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?

Similar Messages

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

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

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

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

  • 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();
    }

  • Non-Blocking Writing and Strings

    Hello.
    My question is simple, is it possible to write strings using a non-blocking method?
    I was praying that there was a method in the NIO API that allowed me to, yet i can't find one.
    If the answer is blatantly obvious please forgive me, i'm tired and hungry :)
    Thank you for looking at this topic

    Strings are written to files or sockets using a certain encoding. I usually use UTF-8, but your application might be different.
    1. Get the SocketChannel from your non-blocking socket.
    SocketChannel ch = mySocket.getChannel(); // mySocket is java.net.Socket2. Make a CharBuffer out of the String you want to send.
    CharBuffer chars = CharBuffer.wrap(myString); // myString is your data3. Encode it so it becomes a ByteBuffer. I'll use the [UTF-8|http://www.joelonsoftware.com/articles/Unicode.html] Charset here.
    ByteBuffer bytes = Charset.forName("UTF-8").encode(chars);4. Use the write(ByteBuffer) method in the SocketChannel from 1.
    ch.write(bytes);Import declarations:
    import java.nio.channels.SocketChannel;
    import java.nio.CharBuffer;
    import java.nio.ByteBuffer;
    import java.nio.charset.Charset;s

  • 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

  • How to handle write errors in non blocking sockets

    Hi,
    I'm using sockets registered with a Selector for read operations. I've seen code examples that put the SocketChannel in non blocking mode before registering it with the selector, and in fact not doing so would cause an IllegalBlockingModeException to be thrown.
    My problem is that I can't handle write errors. The call to write() returns inmediately without throwing any exception. Even worse, when the network timeout expires the selector wakes up and I get an exception on read(). So I can't tell the difference between a real read error and a write error.
    What can I do? Is there a magic method I haven't heard about?
    Thanks

    ejp wrote:
    OK, so what happens is this: you write from your ByteBuffer; if there is room in the socket send buffer, the data is transferred and the transfer count is returned. (If there isn''t, the write returns zero and nothing has happened.) Your application code then continues. Meanwhile TCP is trying to send the data in the send buffer and get an ACK from the peer. If the peer is down as per your test, eventually those write attempts will time out. You will then get a connection reset exception on the next read or write.
    Even worse, when the network timeout expires the selector wakes upCorrect, to tell you there is an error condition pending. This is good, not bad.You're right. This way my program can know that something happened.
    But I still don't understand what the difference between a failed write() and a failed read() is. I mean, the error condition may appear during a send attempt, or it may appear after sending. In both cases I get an error when trying to read. How can my program know if data have been received by the other end?
    Do I have to implement ACK messages in the application level protocol??? It'd be nice if TCP could do this for me...

  • 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 );

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

Maybe you are looking for