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

 

  1. public class ReaderLookup  
  2. {  
  3.     private static final int PORT = 8888;  
  4. //    private Map<Reader,SocketChannel> readerCache = new Hashtable<Reader, SocketChannel>();   
  5.     private List<SelectionKey> keyCache = new ArrayList<SelectionKey>();  
  6.       
  7.     public void lookupAllReaders(){  
  8.         try  
  9.         {  
  10.             // Create a new server socket channel and set to non blocking mode  
  11.             ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();  
  12.             serverSocketChannel.configureBlocking(false);  
  13.               
  14.             // Bind the server socket to local host   
  15.             ServerSocket serverSocket = serverSocketChannel.socket();  
  16.             serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(),PORT));  
  17.               
  18.             // Get a selector  
  19.             Selector selector = Selector.open();  
  20.               
  21.             // Register accepts on the server socket with the selector. This  
  22.             // step tells the selector that the socket wants to be put on the  
  23.             // ready list when accept operations occur, so allowing multiplexed  
  24.             // non-blocking I/O to take place.  
  25.             SelectionKey key_ServerSocketChannel = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);  
  26.               
  27.             int keys = 0 ;  
  28.             while( (keys = selector.select()) > 0 ){  
  29.                 // Get selected keys  
  30.                 Set selectedKeys = selector.selectedKeys();  
  31.                   
  32.                 Iterator iterator = selectedKeys.iterator();  
  33.                 while (iterator.hasNext())  
  34.                 {  
  35.                     SelectionKey key = (SelectionKey) iterator.next();  
  36.                     iterator.remove();  
  37.                     if(key.isAcceptable()){  
  38.                         ServerSocketChannel tmpServerSocketChannel =  (ServerSocketChannel) key.channel();  
  39.                         // The accept() returned immediately because the ServerSocketChannel was working on non-blocking mode  
  40.                         SocketChannel client = tmpServerSocketChannel.accept();  
  41.                           
  42.                         // 最好不要注册写状态SelectionKey.OP_WRITE,因为写状态在任何时候都是ready的,都会被select(),影响性能  
  43.                         client.configureBlocking(false);  
  44.                         SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ);  
  45.                           
  46.                         // Save the client channel's selectionkey for write databuffer  
  47.                         keyCache.add(clientKey);  
  48.                     }else if(key.isReadable()){  
  49.                         System.out.println(key.readyOps());  
  50.                         int dataLength = 4;  
  51.                         ByteBuffer dst = ByteBuffer.allocate(dataLength);   
  52.                         SocketChannel socketChannel = (SocketChannel) key.channel();  
  53.   
  54.                         socketChannel.read(dst);  
  55. //                        dst.flip();  
  56.                           
  57. //                            // Do something with the bytebuffer  
  58.                             dst.flip();  
  59.                             Charset charset = Charset.forName("us-ascii");  
  60.                             CharsetDecoder decoder = charset.newDecoder();  
  61.                             CharBuffer charBuffer = decoder.decode(dst);  
  62.                             if(charBuffer.toString().equals("w")){  
  63.                                 writeMsg(socketChannel.keyFor(selector));  
  64.                             }else{  
  65.                                 dst.flip();  
  66.                                 socketChannel.write(dst);  
  67.                             }  
  68. //                            System.out.println(charBuffer.toString());  
  69.                          
  70.                     }  
  71.                 }  
  72.                 }  
  73.         }  
  74.         catch (IOException e)  
  75.         {  
  76.             // TODO Auto-generated catch block  
  77.             e.printStackTrace();  
  78.         }  
  79.     }  
  80.       
  81.     private void writeMsg(SelectionKey selectionKey) throws IOException  
  82.     {  
  83.         // TODO Auto-generated method stub  
  84.         ByteBuffer bf = ByteBuffer.wrap("It isn't through selector!".getBytes());  
  85.         ((SocketChannel)selectionKey.channel()).write(bf);  
  86.     }  
  87.   
  88.     public static void main(String[] args)  
  89.     {  
  90.         ReaderLookup main = new ReaderLookup();  
  91.         main.lookupAllReaders();  
  92.     }  
  93. }  

 

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

 

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

 

  1. while( (keys = selector.select()) > 0 ){  
  2.                 // Get selected keys  
  3.                 Set selectedKeys = selector.selectedKeys();  
  4.                   
  5.                 Iterator iterator = selectedKeys.iterator();  
  6.                 while (iterator.hasNext())  
  7.                 {  
  8.                     SelectionKey key = (SelectionKey) iterator.next();  
  9.                     iterator.remove();  
  10.                       
  11.                     if(key.isAcceptable()){  
  12.                         ServerSocketChannel tmpServerSocketChannel =  (ServerSocketChannel) key.channel();  
  13.                         // The accept() returned immediately because the ServerSocketChannel was working on non-blocking mode  
  14.                         SocketChannel client = tmpServerSocketChannel.accept();  
  15.                           
  16.                         // 最好不要注册写状态SelectionKey.OP_WRITE,因为写状态在任何时候都是ready的,都会被select(),影响性能  
  17.                         client.configureBlocking(false);  
  18.                         SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ );  
  19.                           
  20.                         // Save the client channel's selectionkey for write databuffer  
  21.                         keyCache.add(clientKey);  
  22.                     }else if(key.isReadable()){  
  23.                         SocketChannel socketChannel = (SocketChannel) key.channel();  
  24.   
  25.                           
  26.                         ByteBuffer dstBuffer = ByteBuffer.allocate(BUFFER_SIZE);   
  27.                           
  28.                         int count ;  
  29.                         while( (count = socketChannel.read(dstBuffer)) > 0){  
  30.                             dstBuffer.flip();  
  31.                               
  32.                             // Do something with the bytebuffer  
  33.                             Charset charset = Charset.forName("us-ascii");  
  34.                             CharsetDecoder decoder = charset.newDecoder();  
  35.                             CharBuffer charBuffer = decoder.decode(dstBuffer);  
  36.                             if(charBuffer.toString().equals("w")){  
  37.                                 writeMsg(socketChannel.keyFor(selector));  
  38.                             }else{  
  39.                                 dstBuffer.flip();  
  40.                                 socketChannel.write(dstBuffer);  
  41.                             }  
  42.                               
  43.                             dstBuffer.clear();  
  44.                         }//end while( (count = socketChannel.read(dst)) > 0){  
  45.                           
  46.                         //链接异常中断,关闭channel  
  47.                         if(count < 0){  
  48.                             socketChannel.close();  
  49.                         }                          
  50.                           
  51.                     }//end else if(key.isReadable()){  
  52.                 }//end while (iterator.hasNext())  
  53.             }//end while( (keys = selector.select()) > 0 ){  
  54.         }  

 

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

posted @ 2013-09-26 15:39  trenail  阅读(2645)  评论(0)    收藏  举报