Java nio, проверяет, готов ли канал к чтению, записи

StackOverflow https://stackoverflow.com/questions/1450777

  •  12-09-2019
  •  | 
  •  

Вопрос

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

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

Хорошая ли это идея, есть ли лучший способ сделать это, и на что мне следует обратить внимание?Например, в Учебное пособие по Rox состояния "Если вы попытаетесь смешивать операции ЧТЕНИЯ и записи, вы быстро наживете на неприятности.Было замечено, что реализация Sun Windows заходит в тупик, если вы сделаете это ". Есть ли здесь подобные ошибки?Каков наилучший способ реализации:

boolean isReadyForRead(SocketChannel c);
boolean isReadyForWrite(SocketChannel c);
Это было полезно?

Решение

Как насчет чего-нибудь подобного?

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

Другие советы

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top