[英]java.nio.channels.SocketChannel for both periodic write and immediate read
I want to write a client application which send messages to server and receive its reply. 我想编写一个客户端应用程序,将消息发送到服务器并接收其回复。 The client sends messages many times (for example one message in very second periodically) regardless of replies.
客户端多次发送消息(例如,定期在第二秒发送一条消息),而不管答复。 When a reply comes back, the client want to respond as quickly as possible.
当回复返回时,客户希望尽快做出响应。
Here's the code, which does not work, of the client. 这是客户端的无效代码。 I want the runnable instance in
startReading()
method should respond to the reply from the server but it does not. 我希望
startReading()
方法中的runnable实例应响应来自服务器的答复,但事实并非如此。 In this case, _channel.write(buffer)
does not return properly. 在这种情况下,
_channel.write(buffer)
无法正确返回。
Please let me know the problem of the following code or some other way to implement the above behavior. 请让我知道以下代码或实现上述行为的其他方式的问题。
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);
}
}
You're ignoring the return code from channel.write()
. 您将忽略
channel.write()
的返回代码。 It isn't obliged to write the whole buffer. 不必写整个缓冲区。 In non-blocking mode it isn't obliged to write anything at all.
在非阻塞模式下,完全不必写任何东西。
You must do as follows: 您必须执行以下操作:
buffer.remaining()
is zero, you're done: compact()
the buffer and return. buffer.remaining()
为零,则说明操作完成: compact()
缓冲区并返回。 buffer.remaining()
is non -zero, the socket send buffer is full, so you have to (a) compact the buffer (b) register for OP_WRITE
instead of OP_READ
and (c) return to the select loop. buffer.remaining()
不为零,则套接字发送缓冲区已满,因此您必须(a)压缩缓冲区(b) OP_WRITE
而不是OP_READ
寄存器,并且(c)返回选择循环。 When the channel becomes writable, repeat as from (1) above, and this time if you get success as at (2) go back to registering for OP_READ
instead of OP_WRITE
. OP_READ
而不是OP_WRITE
。 In other words you are waiting for the selector to tell you when there is space in the socket send buffer;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.