socketchannel在客户端链接断开时的问题

public class ReaderLookup { private static final int PORT = 8888; // private Map readerCache = new Hashtable(); private List keyCache = new ArrayList(); public void lookupAllReaders(){ try { // Create a new server socket channel and set to non blocking mode ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); // Bind the server socket to local host ServerSocket serverSocket = serverSocketChannel.socket(); serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(),PORT)); // Get a selector Selector selector = Selector.open(); // 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 key_ServerSocketChannel = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); int keys = 0 ; while( (keys = selector.select()) > 0 ){ // Get selected keys Set selectedKeys = selector.selectedKeys(); Iterator iterator = selectedKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); iterator.remove(); if(key.isAcceptable()){ ServerSocketChannel tmpServerSocketChannel = (ServerSocketChannel) key.channel(); // The accept() returned immediately because the ServerSocketChannel was working on non-blocking mode SocketChannel client = tmpServerSocketChannel.accept(); // 最好不要注册写状态SelectionKey.OP_WRITE,因为写状态在任何时候都是ready的,都会被select(),影响性能 client.configureBlocking(false); SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ); // Save the client channel's selectionkey for write databuffer keyCache.add(clientKey); }else if(key.isReadable()){ System.out.println(key.readyOps()); int dataLength = 4; ByteBuffer dst = ByteBuffer.allocate(dataLength); SocketChannel socketChannel = (SocketChannel) key.channel(); socketChannel.read(dst); // dst.flip(); // // Do something with the bytebuffer dst.flip(); Charset charset = Charset.forName("us-ascii"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(dst); if(charBuffer.toString().equals("w")){ writeMsg(socketChannel.keyFor(selector)); }else{ dst.flip(); socketChannel.write(dst); } // System.out.println(charBuffer.toString()); } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void writeMsg(SelectionKey selectionKey) throws IOException { // TODO Auto-generated method stub ByteBuffer bf = ByteBuffer.wrap("It isn't through selector!".getBytes()); ((SocketChannel)selectionKey.channel()).write(bf); } public static void main(String[] args) { ReaderLookup main = new ReaderLookup(); main.lookupAllReaders(); } }

当客户端的链接异常断开,此时代表这个链接的channel一直处于readable的状态,如何检查链接已断开呢?

 

一段时间的试验发现,链接断开后,虽然该channel的ready operation是OP_READ,但是此时channel.read(buffer)返回-1,此时可以增加一个判断

while( (keys = selector.select()) > 0 ){ // Get selected keys Set selectedKeys = selector.selectedKeys(); Iterator iterator = selectedKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); iterator.remove(); if(key.isAcceptable()){ ServerSocketChannel tmpServerSocketChannel = (ServerSocketChannel) key.channel(); // The accept() returned immediately because the ServerSocketChannel was working on non-blocking mode SocketChannel client = tmpServerSocketChannel.accept(); // 最好不要注册写状态SelectionKey.OP_WRITE,因为写状态在任何时候都是ready的,都会被select(),影响性能 client.configureBlocking(false); SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ ); // Save the client channel's selectionkey for write databuffer keyCache.add(clientKey); }else if(key.isReadable()){ SocketChannel socketChannel = (SocketChannel) key.channel(); ByteBuffer dstBuffer = ByteBuffer.allocate(BUFFER_SIZE); int count ; while( (count = socketChannel.read(dstBuffer)) > 0){ dstBuffer.flip(); // Do something with the bytebuffer Charset charset = Charset.forName("us-ascii"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(dstBuffer); if(charBuffer.toString().equals("w")){ writeMsg(socketChannel.keyFor(selector)); }else{ dstBuffer.flip(); socketChannel.write(dstBuffer); } dstBuffer.clear(); }//end while( (count = socketChannel.read(dst)) > 0){ //链接异常中断,关闭channel if(count < 0){ socketChannel.close(); } }//end else if(key.isReadable()){ }//end while (iterator.hasNext()) }//end while( (keys = selector.select()) > 0 ){ }

//链接异常中断,关闭channel
if(count < 0){
socketChannel.close();
}

 

你可能感兴趣的:(iterator,socket,dst,server,buffer,string)