我正在使用AsynchronousServerSocketChannel
. 出于测试目的,我创建了一个小型客户端原型,它发送两条消息,"hi"
然后"stackoverflow"
断开连接。在服务器端,我读取到达的消息并将它们打印到标准输出。当客户端执行时,我期望收到:
message [hi], bytecount 2
message [stackoverflow], bytecount 13
问题是,有时当服务器调用读取回调时两条消息都已经到达,所以我得到
message [histackoverflow], bytecount 15
反而。
问题是,是否可以在服务器端确保消息单独到达,如果可以,如何做到这一点?
这是我CompletionHandler
处理客户端连接的原型:
class CommunicationHandler implements CompletionHandler<AsynchronousSocketChannel, Void> {
private final AsynchronousServerSocketChannel server;
public CommunicationHandler(final AsynchronousServerSocketChannel server) {
this.server = server;
}
@Override
public void failed(Throwable ex, Void attachment) {}
@Override
public void completed(final AsynchronousSocketChannel client, Void attachment) {
// handle client messages
final ByteBuffer buffer = ByteBuffer.allocateDirect(Server.BUFFER_SIZE);
final Session session = new Session();
try {
client.read(buffer, session, new CompletionHandler<Integer, Session>() {
@Override
public void completed(Integer byteCount, final Session currSession) {
if (byteCount == -1) {
return;
}
buffer.flip();
// TODO forward buffer to message handler (probably protocol?)
System.out.println("message [" + convertToString(buffer) + "], byteCount " + byteCount);
buffer.clear();
// read next message
client.read(buffer, currSession, this);
}
@Override
public void failed(Throwable ex, final Session currSession) {}
});
}
// accept the next connection
server.accept(null, this);
}
ByteBuffer
转换String
:
public static String convertToString(ByteBuffer bb) {
final byte[] bytes = new byte[bb.remaining()];
bb.duplicate().get(bytes);
return new String(bytes);
}
这是一个测试客户端原型:
public class Client {
public final void start() {
try (AsynchronousSocketChannel client = AsynchronousSocketChannel.open();) {
Future<Void> connCall = client.connect(InetAddress.getByName("127.0.0.1"), 8060));
connCall.get();
// client is now connected
// send greeting message
Future<Integer> writeCall = client.write(Charset.forName("utf-8").encode(CharBuffer.wrap("hi")));
writeCall.get();
// Thread.sleep(5000L);
writeCall = client.write(Charset.forName("utf-8").encode(CharBuffer.wrap("stackoverflow")));
writeCall.get();
client.close();
} catch (IOException e) {
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
}
}