0

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

大概这可以通过将所有通道放入一个选择器中进行读取,并在它们出现时将它们标记为准备读取,然后对写入执行相同的操作,然后从我标记为就绪的通道中进行选择。

这是一个好主意吗,有没有更好的方法来做到这一点,我应该注意什么?例如,Rox 教程指出“如果您尝试混合使用 OP READ 和 OP WRITE,您很快就会陷入困境。如果您这样做,Sun Windows 实现已被视为死锁。” 这里有类似的陷阱吗?最好的实施方式是什么:

boolean isReadyForRead(SocketChannel c);
boolean isReadyForWrite(SocketChannel c);
4

2 回答 2

6

You should be using your SelectionKey's to verify if a socket is ready for read or write, when the selector wakes up.

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

于 2009-09-20T16:07:34.823 回答
2

这样的事情怎么样?

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() 旨在有效地告诉您套接字的状态,每个人都应该直接使用它。

于 2009-09-20T19:25:04.127 回答