qq_28775501 2018-06-23 09:51 采纳率: 0%
浏览 1808
已结题

java nio selector.select不阻塞

java nio selector.select不阻塞

java nio 构建的服务端在与客户端(用ubuntu虚拟机的netcat)连接上后,
netcat直接ctrl + d(什么内容都不输入)的话,服务端的selector.select()方法的结果就一直是0
也不阻塞了。请问这是为什么。
代码如下:

 package chapter4;

import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class List4_2 {

    @Test
    public void test1(){
        PlainNIOServer server = new PlainNIOServer();
        try {
            server.serve(12345);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class PlainNIOServer {
        public void serve(int port) throws IOException {//在对方连接上以后直接ctrl+d会陷入readable的死循环
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.configureBlocking(false);
            serverChannel.bind(new InetSocketAddress(port));
            Selector selector = Selector.open();
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);

            while(true){
                if (selector.select() == 0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
//                    continue;
                }
                Set<SelectionKey> keys = selector.selectedKeys();
                Iterator<SelectionKey> it = keys.iterator();
                while (it.hasNext()){
                    SelectionKey key = it.next();
                                        it.remove();
                    System.out.println("acc : " + key.isAcceptable() + ", w : " + key.isWritable()
                            + ", r : " + key.isReadable() + ", conn : " + key.isConnectable() + ", v : " + key.isValid());
                    try {
                        if (key.isAcceptable()) {
                            ServerSocketChannel server = (ServerSocketChannel) key.channel();
                            SocketChannel client = server.accept();
                            if (client != null) {
                                client.configureBlocking(false);
                                client.register(selector, SelectionKey.OP_READ);
                                System.out.println("Accept Connection from " + client);
                            }
                        }
                        if (key.isReadable()) {
                            SocketChannel client = (SocketChannel) key.channel();
                            ByteBuffer byteBuffer = ByteBuffer.allocate(5);
                            System.out.println("readable !!!");
                            int count = 0;
                            while (( count = client.read(byteBuffer)) > 0 ) {
                                byteBuffer.flip();
                                byte[] bytes = new byte[1024];
                                while (byteBuffer.hasRemaining()) {
                                    byteBuffer.get(bytes, 0, Math.min(byteBuffer.remaining(), bytes.length));
                                    String sentence;
                                    System.out.println(sentence = new String(bytes, 0, count));
                                    byteBuffer.compact();
                                    byteBuffer.put(sentence.getBytes());
                                    byteBuffer.flip();
                                    client.write(byteBuffer);
                                }
                                byteBuffer.compact();
                            }
                        }
                    }
                    catch (Exception e){
                        e.printStackTrace();
                        key.channel().close();
                    }
                }
            }
        }
    }
}

运行如上代码以后,在虚拟机里运行netcat , 截图如下
图片说明
此时在netcat中按下ctrl + d (EOF)则服务端的selector.select方法调用之后返回结果一直为0且不再阻塞,所有连上的客户端也没办法发消息了。
服务端效果如下:
图片说明

  • 写回答

1条回答 默认 最新

  • 懒散猴 2020-07-12 20:44
    关注

    搜索下nio空轮询bug ,是 jdk的bug 可以借鉴netty的避免方案,就是一个周期内空轮询的次数超过一个阈值新建新的selector替代旧的selector

    评论

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况