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

public class ReaderLookup { private static final int PORT = 8888; // private Map<Reader,SocketChannel> readerCache = new Hashtable<Reader, SocketChannel>(); private List<SelectionKey> keyCache = new ArrayList<SelectionKey>(); 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();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值