0

私の目標は、クライアントからサーバーにさまざまな種類のメッセージを送信することであり、テキストベースになります。私が確信が持てないのは、ここで部分的な読み取りをどのように行うかです。メッセージ全体を確実に受け取る必要があり、それ以上のものはありません。

誰もそれを経験したことがありますか?

これが私がこれまでに持っているものです:

    private void handleNewClientMessage(SelectionKey key) throws IOException {
    SocketChannel sendingChannel = (SocketChannel) key.channel();

    ByteBuffer receivingBuffer = ByteBuffer.allocate(2048);
    int bytesRead = sendingChannel.read(receivingBuffer);
    if (bytesRead > 0) {
        receivingBuffer.flip();

        byte[] array = new byte[receivingBuffer.limit()];
        receivingBuffer.get(array);
        String message = new String(array);

        System.out.println("Server received "  +message);           
    }
    selector.wakeup();
}

しかし、私にはメッセージを「終わらせる」方法がなく、確実に 1 つの完全なメッセージを持つようにします。

よろしくお願いします、O

4

1 に答える 1

3

一度に 1 バイトしか読み取らない限り、2 つ以上のメッセージを読み取ることは決してありません。(これはお勧めしません)。

代わりに、できるだけ多くを ByteBuffer に読み込み、それを解析してメッセージの終わり (テキストの改行など) を見つけます。

行末が見つかったら、それを抽出して文字列に変換して処理します。メッセージが部分的になるまで (または何も残らないようになるまで) 繰り返します。

メッセージの一部しかないことがわかった場合は、compact() (position() > 0 の場合) を実行し、さらに read() を試みます。

これにより、一度にできるだけ多くのメッセージを読むことができますが、不完全なメッセージも処理できます。

注: 接続用に ByteBuffer を保持する必要があるため、以前に読んだ部分的なメッセージがわかります。

注: バッファ サイズより大きいメッセージがある場合、これは機能しません。私は、例えば 1+ MB のリサイクルされたダイレクト ByteBuffer を使用することをお勧めします。ダイレクト ByteBuffers では、使用される ByteBuffer のページのみが実メモリに割り当てられます。

パフォーマンスが気になる場合はbyte[]、可能な限り再利用します。すでにあるスペースよりも多くのスペースが必要な場合にのみ、再割り当てする必要があります。

ところで、Plain IO で BufferedReader を使用する方がはるかに簡単に使用できますが、パフォーマンスは十分です。

于 2013-04-25T14:36:56.357 に答える