を使用して単純なサーバーを実装していますAsynchronousServerSocketChannel
。テスト目的で、2 つのメッセージを送信して"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) {
}
}