Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SelectionKey不可写_Java_Nio - Fatal编程技术网

Java SelectionKey不可写

Java SelectionKey不可写,java,nio,Java,Nio,我很好奇为什么代码总是告诉我“密钥不可写”?我的密码有什么问题吗?每次套接字读取某些内容时,我都将密钥设置为对OP_WRITE感兴趣,并测试它是否可写。然而,它总是说不可写。我完全是Java套接字编程的新手 顺便说一下,我不会关闭客户 public final class DateServer { private DateServer() { throw new IllegalStateException("Instantiation not allowed"); }

我很好奇为什么代码总是告诉我“密钥不可写”?我的密码有什么问题吗?每次套接字读取某些内容时,我都将密钥设置为对OP_WRITE感兴趣,并测试它是否可写。然而,它总是说不可写。我完全是Java套接字编程的新手

顺便说一下,我不会关闭客户

public final class DateServer {

    private DateServer() {
    throw new IllegalStateException("Instantiation not allowed");
    }

    public static void main(final String[] args) throws Exception {
        try (final Selector selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open();) {
            InetSocketAddress hostAddress = new InetSocketAddress("127.0.0.1", 9999);
            serverSocket.bind(hostAddress);

            serverSocket.configureBlocking(false);
            serverSocket.register(selector, serverSocket.validOps(), null);

            while (true) {
                int numSelectedKeys = selector.select();
                if (numSelectedKeys > 0) {
                    handleSelectionKeys(selector.selectedKeys(), serverSocket);
                }
            }
        }
    }

    private static void handleSelectionKeys(Set<SelectionKey> selectionKeys, ServerSocketChannel serverSocket) throws IOException {

    Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
    while (selectionKeyIterator.hasNext()) {
        SelectionKey key = selectionKeyIterator.next();

        if (key.isAcceptable()) {
            acceptClientSocket(key, serverSocket);
        } else if (key.isReadable()) {
            readRequest(key);
        }

        selectionKeyIterator.remove();
    }
    }

    private static void acceptClientSocket(SelectionKey key, ServerSocketChannel serverSocket) throws IOException {

        SocketChannel client = serverSocket.accept();
        client.configureBlocking(false);
        client.register(key.selector(), SelectionKey.OP_READ);

        System.out.println("Accepted connection from client");
    }

    private static void readRequest(SelectionKey key) throws IOException {

        SocketChannel client = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        int bytesRead = client.read(buffer);

        if (bytesRead == -1) {
            client.close();
        } else {
            System.out.println(String.format("Request data: %s", new String(buffer.array())));
            int interestOps = 0;
            interestOps |= SelectionKey.OP_WRITE;
            key.interestOps(interestOps);

            if (key.isWritable()){
                System.out.println("key is writable");
            } else {
                System.out.println("key is not writable");
            }

            interestOps = 0;
            interestOps |= SelectionKey.OP_READ;
            key.interestOps(interestOps);
        }

    }
}
公共最终类DateServer{
专用数据服务器(){
抛出新的IllegalStateException(“不允许实例化”);
}
公共静态void main(最终字符串[]args)引发异常{
尝试(最终选择器=选择器.open();ServerSocketChannel serverSocket=ServerSocketChannel.open();){
InetSocketAddress主机地址=新的InetSocketAddress(“127.0.0.1”,9999);
绑定(主机地址);
serverSocket.configureBlocking(false);
寄存器(选择器,serverSocket.validOps(),null);
while(true){
int numSelectedKeys=selector.select();
如果(numSelectedKeys>0){
handleSelectionKeys(selector.selectedKeys(),serverSocket);
}
}
}
}
私有静态void handleSelectionKeys(设置selectionKeys、ServerSocketCannel serverSocket)引发IOException{
迭代器selectionKeyIterator=selectionKeys.Iterator();
while(selectionKeyIterator.hasNext()){
SelectionKey=selectionKeyIterator.next();
if(key.isAcceptable()){
acceptClientSocket(密钥、服务器套接字);
}else if(key.isReadable()){
读取请求(密钥);
}
selectionKeyIterator.remove();
}
}
私有静态void acceptClientSocket(SelectionKey key,ServerSocketChannel serverSocket)引发IOException{
SocketChannel client=serverSocket.accept();
client.configureBlocking(false);
client.register(key.selector(),SelectionKey.OP_READ);
System.out.println(“接受来自客户端的连接”);
}
私有静态void readRequest(SelectionKey key)引发IOException{
SocketChannel客户端=(SocketChannel)key.channel();
ByteBuffer缓冲区=ByteBuffer.allocate(1024);
int bytesRead=client.read(缓冲区);
如果(字节读==-1){
client.close();
}否则{
System.out.println(String.format(“请求数据:%s”),新字符串(buffer.array());
int=0;
interesttops |=SelectionKey.OP|u WRITE;
关键字:interestOps(interestOps);
if(key.isWritable()){
System.out.println(“密钥可写”);
}否则{
System.out.println(“密钥不可写”);
}
利率=0;
interesttops |=SelectionKey.OP|u READ;
关键字:interestOps(interestOps);
}
}
}

注册客户端时,只需指定
SelectionKey.OP\u READ
,因此频道永远不会准备好写入。(查看Selectionkey.java中的isWritable方法)

在您的情况下,OP_WRITE从未注册,因此无法工作

用这个让它工作


client.register(key.selector(),SelectionKey.OP_READ | SelectionKey.OP_WRITE)

按钮只告诉选择器下次要选择什么。设置OP_WRITE不会神奇地使选择键具备预测未来的能力。您必须再次调用
select()
,才能根据此代码实际设置OP_WRITE


但是您不需要选择器的“权限”来写入通道。你只需要写,而且只有当写计数为零时,你才需要担心操作写入,正如这里关于该主题的众多答案所示。

你的意思是
key.interesttops(interesttops)之后不生效?你能解释一下原因吗?好问题。我只是注意到了。我需要调查为什么不起作用。是的,您当前的实现不起作用,因为键选择器当前处于读取模式,而在其处于读取模式时,您不能仅仅添加另一个感兴趣的操作(根据我的调查),并期望在您当前读取时键返回isWriteable()。尽管如此,您仍然可以向channel写入。阅读你有两种方法来修复它1。正如我在回答2中提到的。一旦你读了你需要读的内容,你就把OP_WRITE添加到键中。一个通道总是可以写的,除非它的套接字发送缓冲区中没有空间。没有“处于读取模式”的选择器。回答和评论都是胡说八道。这并不能回答为什么OP正在获取密钥不可写的问题。@Sneh它就是这么做的。把第一段再读一遍。特别是第二句话。@EJP谢谢。我得到了它。如果有任何官方文件解释这一点会更好。我确实在@EJP正确地阅读了你的段落。您编辑并添加了“您必须再次调用select(),以使OP_WRITE能够作为此代码的结果进行实际设置。”这正是您的答案中缺少的部分。而且您还犯了更愚蠢的错误。我没有做任何不正确的陈述。别告诉我该怎么看东西。荣誉
public final boolean isWritable() {
    return (readyOps() & OP_WRITE) != 0;
}