Сервер NIO не может прослушивать клиент

58
8

Привет, я пытаюсь реализовать простой сервер Java NIO; который регистрирует socketChannel с селектором. Поэтому я хочу послушать клиента и отправить ответ. После того, как socketChannel зарегистрирован в селекторе, даже если клиент (не NIO) отправляет некоторые данные, сервер не может читать; howerver генерируемый ключ все еще повторяется.


Подробный просмотр: сторона сервера:


**First thread**:

public void run() {
while (true) {


    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(true);
serverSocketChannel.socket().bind(inetAdressOfServer);
SocketChannel clientChannel = serverSocketChannel.accept();
new Listener("").addSocketChannel(clientChannel);

}}

**Second Thread**:

static Selector selector = Selector.open();
public boolean addSocketChannel(SocketChannel clientChannel) {

SelectionKey key = clientSocketChannel.register(selector, selector.OP_READ|SelectionKey.OP_WRITE);
key.attach(new ChannelCallback(clientSocketChannel));
return key.isValid();
}

public void run() {

Set keysSet = selector.keys();
Iterator i = keysSet.iterator();
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
}

if (key.isReadable()) {
//read and do something
}
}

Client Side:

Socket socket = new Socket(serverIP, serverPort);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeBytes(str + "\n");


NB: когда выполняется в одном потоке, работает одна и та же программа, но когда она реализована в соответствии с указанным выше способом, это не позволяет слушать клиента.
Пожалуйста, помогите мне решить эту проблему.

спросил(а) 2009-05-25T14:44:00+04:00 11 лет, 4 месяца назад
1
Решение
56

Очень сложно понять, что вы там сделали, но похоже, что то, что вы отметили как "второй поток", используется обоими потоками (некоторая путаница в реализации Runnable/extend Thread и реальных потоков?). В частности, я предполагаю конструкцию new Listener и запускает поток. Затем вы вызываете addSocketChannel в первом потоке. Поэтому есть условие гонки.

Также это плохая идея сделать selector static.

ответил(а) 2009-05-25T15:40:00+04:00 11 лет, 4 месяца назад
57

Чтение чтения чтения из другого потока, вот очевидные проблемы с вашим кодом.


public void run() {
Set keysSet = selector.keys();

Здесь вы берете набор ключей из итератора, но нет кода, когда-либо делающего select() или selectNow() на селекторе, поэтому этот набор всегда будет пустым.


    Iterator i = keysSet.iterator();        
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
}
if (key.isReadable()) {
//read and do something
}
}

Это даже не компилируется, проверка на "чтение" на ключе должна выполняться внутри блока while.

SelectionKey key = clientSocketChannel.register(selector,
SelectionKey.OP_READ |
SelectionKey.OP_WRITE);

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


Вы должны только установить SelectionKey.OP_WRITE, если вы на самом деле планируете писать.


Наконец, использование двух потоков здесь очень нетрадиционно. Рекомендуемый способ сделать это - зарегистрировать ServerSocketChannel для селектора с помощью OP_ACCEPT и запустить accept на ServerSocket в том же потоке, что и чтение/запись.

ответил(а) 2009-05-25T21:27:00+04:00 11 лет, 4 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема