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

    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog