代码之家  ›  专栏  ›  技术社区  ›  mk.

Java NIO,检查信道是否已准备好用于读、写

  •  0
  • mk.  · 技术社区  · 15 年前

    我不想用通常的方式使用选择器,在这里可以确定和发送每个就绪通道的消息,我想选择当前准备好的连接,并在那里发送消息。

    大概这可以通过把所有的频道都放到一个选择器中进行阅读,如果它们出来了,就把它们标记为准备阅读,然后对写作进行同样的操作,然后从我标记为准备好的频道中进行选择来完成。

    这是个好主意吗?有没有更好的方法来做这个?我应该注意什么?例如, Rox Tutorial 状态 “如果你试图把读写结合起来,你会很快陷入麻烦。如果这样做,Sun Windows实现会死锁。” 这里有类似的陷阱吗?实施的最佳方法是什么:

    boolean isReadyForRead(SocketChannel c);
    boolean isReadyForWrite(SocketChannel c);
    
    2 回复  |  直到 10 年前
        1
  •  2
  •   ZZ Coder    15 年前

    像这样的怎么样?

    public static boolean isReadyForRead(SocketChannel socket) throws IOException {
        return isReady(socket, SelectionKey.OP_READ);
    }
    
    public static boolean isReadyForWrite(SocketChannel socket) throws IOException {
        return isReady(socket, SelectionKey.OP_WRITE);
    }
    
    public static boolean isReady(SocketChannel socket, int op) throws IOException {
        // Setup
        if (socket.isBlocking()) 
            throw new IllegalArgumentException("Socket must be in non-blocking mode");
    
        Selector selector = SelectorProvider.provider().openSelector();
        socket.register(selector, op);
    
        // Real work
        if (selector.selectNow() == 0)
            return false;
        // Just in case selector has other keys
        return selector.selectedKeys().contains(socket.keyFor(selector));
    }
    

    这个调用效率非常低,因为它每次都进行设置。如果您有一个封闭类,那么应该将其移出。如果知道选择器只包含一个键,则最后一行可以更改为“ return true; “。

    我这么做只是为了好玩。我想不出这样做有用的情景。select()旨在有效地告诉您套接字的状态,每个人都应该直接使用它。

        2
  •  6
  •   Malaxeur    15 年前

    当选择器唤醒时,您应该使用SelectionKey来验证套接字是否准备好读或写。

    这里有一个 非常 编写NIO服务器和客户端的有用教程 http://rox-xmlrpc.sourceforge.net/niotut/