我一直在使用AsychronousSockets,但在运行大量负载时遇到了接收ReadPendingException的问题。
一些上下文:我希望客户端异步地向服务器发送消息,然后侦听响应。
响应可以是3种类型之一,AsynchronousSocketChannel的读取需要预定大小的ByteBuffer。
因此,我的解决方案是有两个读:一个先接收消息的类型(传入为4个字节,一个int),然后另一个读取,它将构造适当大小的字节缓冲区来处理消息的其余部分。
我认为,这里的主要问题在于,当调用CompletetionHandler的完整方法时,并不一定意味着ByteBuffer的读取是完全的。为了弥补这一点,我创建了一个will循环,它将读取到ByteBuffer已满为止。
然而,while循环中的这个读取似乎偶尔与其他读取发生冲突,这是在我接收到ReadPendingException时。
基本骨架代码:
AsynchronousChannelGroup mThreadGroup= AsynchronousChannelGroup.withFixedThreadPool(100, Executors.defaultThreadFactory());
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(mThreadGroup);
InetSocketAddress hostAddress = new InetSocketAddress("localhost", 12345);
// Connect to server
channel.connect(hostAddress, null, new CompletionHandler<Void, Void>() {
@Override
public void completed(Void result, Void attachment) {
// Write some message to server
ByteBuffer message = ...
channel.write(message, null, new CompletionHandler<Void, Void>() {
@Override
public void completed(Void result, Void attachment) {
// Now that we have sent the message, listen for a response type
ByteBuffer responseType = ...
channel.read(responseType, null, new CompletionHandler<Void, Void>() {
@Override
public void completed(Void result, Void attachment) {
// parse response type, do some other stuff...
// ...
// After other stuff, create new byte buffer for main message
ByteBuffer receiveMessage = ...
channel.read(receiveMessage, null, new CompletionHandler<Void, Void>() {
@Override
public void completed(Void result, Void attachment) {
// The read may not have been completed, so make sure that it is
while (receiveMessage.remaining() > 0) {
channel.read(receiveMessage);
}
// Handle receiveMessage...
}
@Override
public void failed(Throwable exc, Void attachment) {}
});
}
@Override
public void failed(Throwable exc, Void attachment) {}
});
}
public void failed(Throwable exc, Void attachment) {}
});
}
@Override
public void failed(Throwable exc, Void attachment) {}
});因此,我的问题有两方面:
提前谢谢你们的帮助。
发布于 2016-05-19 04:01:40
您不应该在读取完成方法中循环,特别是不首先检查是否有所有数据。您应该首先检查是否收到了所需的所有数据,如果没有,则使用相同的完成方法再进行一次读取。这一过程将恢复,直到它满足第一次测试。
发布于 2016-05-17 05:11:56
我认为这个异常的出现是因为另一个线程正在尝试调用这个completionHandler。访问将需要在readCompletionHandler上同步。或者,尝试删除ReadCompletionHandler中的while(剩余)循环。使用bytesRead参数调用已完成的回调函数。使用此值创建读取消息的缓冲区。例如:
` class ClientReadCompletionHandler实现CompletionHandler {
private AsynchronousSocketChannel socket;
private ByteBuffer readBuffer;
public ClientReadCompletionHandler(AsynchronousSocketChannel socket, ByteBuffer readBuffer) {
this.socket = socket;
this.readBuffer = readBuffer;
System.out.println("readBuffer in constructor: " + readBuffer);
}
@Override
public void completed(Integer bytesRead, IOContext state) {
if (bytesRead != null && bytesRead == -1) {
try {
socket.close();
return;
} catch (IOException e) {
e.printStackTrace();
}
}
byte[] buffer = new byte[bytesRead];
readBuffer.rewind();
// Rewind the input buffer to read from the beginning
readBuffer.get(buffer);
if(readBuffer.hasRemaining()) {
// process this readBuffer somehow to read all remaining data.
// This will not be the place to call socket.read() again.
}
readBuffer.clear();
IOContext readState = new IOContext();
// Now read from socket again.
socket.read(readBuffer, readState, this);
}‘
https://stackoverflow.com/questions/37223693
复制相似问题