开发者社区> 问答> 正文

java nio 关闭客户端服务器端的selector.select(TimeOut)方法为什么不阻塞

代码如下:

// 反复循环,等待IO  
    while (true) {
        // 等待某信道就绪(或超时)  
        if (selector.select(TimeOut) == 0) {// 监听注册通道,当其中有注册的 IO  
                                            // 操作可以进行时,该函数返回,并将对应的  
                                            // SelectionKey 加入 selected-key  
                                            // set
            log.info("服务器独自等待.");
            continue;
        }

        // 取得迭代器.selectedKeys()中包含了每个准备好某一I/O操作的信道的SelectionKey  
        // Selected-key Iterator 代表了所有通过 select() 方法监测到可以进行 IO 操作的 channel  
        // ,这个集合可以通过 selectedKeys() 拿到  
        Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
        while (keyIter.hasNext()) {
            SelectionKey key = keyIter.next();

            try {  
                if (key.isAcceptable()) {
                    // 有客户端连接请求时  
                    protocol.handleAccept(key);
                }  
                if (key.isReadable()) {// 判断是否有数据发送过来  
                    // 从客户端读取数据  
                    protocol.handleRead(key);
                }  
                if (key.isValid() && key.isWritable()) {// 判断是否有效及可以发送给客户端  
                    // 客户端可写时  
                    protocol.handleWrite(key);
                }  
            } catch (IOException ex) {  
                // 出现IO异常(如客户端断开连接)时移除处理过的键 
                log.error("IO异常(如客户端断开连接)", ex);
                keyIter.remove();
                continue;
            }  
            // 移除处理过的键  
            keyIter.remove();
        }
    }

奇怪的现象是,我关闭了客户端后,这个keyIter里面一直会有一个read的key存在,按说客户端关闭了应该阻塞了

展开
收起
蛮大人123 2016-03-17 14:09:26 5351 0
3 条回答
写回答
取消 提交回答
  • } catch (IOException e) {

                    e.printStackTrace();
                    //如果客户端断开 需要结束 不然还会循环进来
                    sk.channel().close();
                } finally {
                    //取消选择键
                    it.remove();
                }
    2019-07-17 19:05:19
    赞同 1 展开评论 打赏
  • socketChannel.read 判断下返回值是否等于负1,若等于负1,关闭通道

    2019-07-17 19:05:19
    赞同 展开评论 打赏
  • 我说我不帅他们就打我,还说我虚伪

    当客户端关闭了之后,相应的客户端的这个socket的read connection也关闭了,所以你在服务器端用select()会在read里得到这个socket的。
    参考U nix Network Programming Vol1的select()部分,里面有一张表格告诉你什么时候一个socket可读、可写、出错。

    2019-07-17 19:05:19
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载