Я хочу написать клиентское приложение, которое отправляет сообщения на сервер и получает его ответ. Клиент отправляет сообщения много раз (например, одно сообщение в очень секунду периодически) независимо от ответов. Когда ответ возвращается, клиент хочет ответить как можно быстрее.java.nio.channels.SocketChannel для периодической записи и немедленного чтения
Вот код, который не работает, клиента. Я хочу, чтобы исполняемый экземпляр в методе startReading()
отвечал на ответ с сервера, но он этого не делает. В этом случае _channel.write(buffer)
не возвращается должным образом.
Пожалуйста, дайте мне знать о проблеме следующего кода или какого-либо другого способа реализации описанного выше поведения.
public class MyClient {
private SocketChannel _channel = null;
private Selector _selector = null;
private InetSocketAddress _addr = new InetSocketAddress("127.0.0.1", 5555);
public MyClient() {
_selector = SelectorProvider.provider().openSelector();
_channel = SocketChannel.open();
_channel.configureBlocking(false);
startReading();
_channel.connect(_addr);
}
private void startReading() throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(1024);
_channel.register(_selector, SelectionKey.OP_READ, buffer);
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
while (0 < _selector.select()) {
Iterator<SelectionKey> keyIterator = _selector.selectedKeys().iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
keyIterator.remove();
if (key.isReadable())
read(key);
}
}
}
catch (IOException e) {}
}
};
ExecutorService service = Executors.newFixedThreadPool(1);
service.execute(runnable);
}
private void read(SelectionKey key) throws IOException {
// do some reading operations
}
@Override
public void run() {
ByteBuffer buffer = ByteBuffer.allocate(1024);
// write message to buffer
buffer.flip();
try {
_channel.write(buffer);
} catch (IOException e) {}
}
public static void main (String[] args) {
MyClient client = new MyClient();
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.scheduleAtFixedRate(client, 1000, 1000, TimeUnit.MILLISECONDS);
}
}
Почему вы возитесь с селектором для одного канала? В конце концов, то, что вы эффективно делаете в своем фоновом потоке, - это повторное внедрение блокирующего чтения. Таким образом, вы можете просто настроить канал для блокировки и сделать обычное чтение в фоновом потоке без этой сложной структуры. – Holger
Зачем использовать селектор для одиночного канала? Поскольку приведенный выше код является упрощенной моделью моей проблемы. То, что я действительно хочу сделать, сложнее. – user4047360