Search code examples
javaexceptionsocketchannel

The write() method of a SocketChannel do not throw an exception when it should do


I'm writing a server to exchange messages among clients. One issue left to be solved is how to release a channel when a client happens to be closed. What I do is to start a monitor thread in which the all-Clients map is monitored, and I attempt to remove() a channel if an exception been detected when trying write() to it. However, after closing a client, the write() method in monitor thread don't throw an exception so the useless channel will never be released. Anybody know why?

public class ServerMonitor extends Thread{
private Map<String, SocketChannel> allClients;
private Set set;
private Iterator it;
private Entry entry;
private SocketChannel channel;
private ByteBuffer buf;

public ServerMonitor(Map<String, SocketChannel> allClients) {
    this.allClients = allClients;
    buf = ByteBuffer.allocateDirect(10);
    byte b = 0;
    buf.put(b);
    buf.flip();
}

public void run(){
    while(true) {
        if(!allClients.isEmpty()) {
            set = allClients.entrySet();
            it = set.iterator();
            while(it.hasNext()) {
                entry = (Entry) it.next();
                channel = (SocketChannel) entry.getValue();
                try{
                    channel.write(buf);
                } catch(Exception e) {
                    allClients.remove(entry.getKey());
                    //set.remove(entry);
                }
            }
        }
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}


Solution

  • Writing to a TCP socket is buffered locally and put on the wire asynchronously. So you can't rely on the first write after the peer closes to fail. You can rely on a subsequent write failing, but it could take a number of writes to get there.