Java nio, проверка готовности канала к чтению, запись - PullRequest
0 голосов
/ 20 сентября 2009

Вместо того, чтобы использовать селектор обычным способом, где для каждого готового канала можно определить и отправить сообщение, я бы хотел выбрать, какое соединение в данный момент готово, и отправить туда сообщение.

Предположительно, это можно сделать, бросив все каналы в селектор для чтения и пометив их как готовые к чтению, если они появятся, затем сделав то же самое для записи, а затем выбрав один из тех, которые я отметил готовыми.

Это хорошая идея, есть ли лучший способ сделать это, и что я должен остерегаться? Например, Rox Tutorial гласит "Если вы попытаетесь смешать OP READ и OP WRITE, вы быстро столкнетесь с проблемами. Реализация Sun Windows зашла в тупик, если вы это сделаете. " Есть ли здесь похожие ошибки? Как лучше всего реализовать:

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

Ответы [ 2 ]

6 голосов
/ 20 сентября 2009

Вы должны использовать вашу SelectionKey для проверки, готов ли сокет для чтения или записи, когда селектор активируется.

Вот очень полезное руководство по написанию NIO-сервера и клиента http://rox -xmlrpc.sourceforge.net / niotut /

2 голосов
/ 20 сентября 2009

Как насчет этого?

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 () предназначена для эффективного информирования вас о состоянии сокетов, и каждый должен использовать это напрямую.

...