Java nio, проверяет, готов ли канал к чтению, записи
Вопрос
Вместо того чтобы использовать селектор обычным способом, где для каждого готового канала может быть определено и отправлено сообщение, я бы хотел выбрать любое соединение, которое в данный момент готово, и отправить сообщение туда.
Предположительно, это можно сделать, поместив все каналы в селектор для чтения и пометив их готовыми к чтению, если они появятся, затем проделав то же самое для записи, а затем выбрав из числа тех, которые я пометил готовыми.
Хорошая ли это идея, есть ли лучший способ сделать это, и на что мне следует обратить внимание?Например, в Учебное пособие по 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/