0

Java サーバーを使用して、安全な WebSocket を備えたブラウザーに接続しています。すべてが接続で正常に動作しますが、多くの場合、socket.in.read(buffer,off,len) から予期しない -1 の結果が返されます。これはフレームの途中でも発生します。通常、ストリームの終わりであるため、-1 を受信するとすぐにソケットを閉じます。ただし、接続のリセットでも発生する可能性があることに注意してください。私のテストでは、読み取り後に貴重なデータを返すソケットが -1 を返すという多くのケースに遭遇しました。私はこれが頻繁にあるとさえ感じています。私の問題は、そのような場合にソケットからスクランブルされたデータを取得することがある場合に発生します。もう 1 つの問題は、フレームが配信されない場合に相手側に通知されないことです... では、TCP/SSL の利点は何でしょうか? Javaでwebsocketフレームを転送するための信頼できない接続と考える必要がある場合?

パケットの到着を確実にするための信頼できない接続に対処するために使用するスキームがいくつかあります。しかし、読み取りが -1 を返した後に何をすべきかを誰かが知っていることを願っています。

この説明がやや曖昧で申し訳ありません... この問題の解決にうんざりしています。

ごみが入ってくる例 (JSON データを含むテキスト フレームのみが送信されます):

16-06-13 22:43:13.918;WebSocket;7: Read frame from websocket: 377, opcode:UNKNOWN
data: null
16-06-13 22:43:13.918;WebSocket;7: Read frame from websocket: 377, opcode:PONG_FRAME
data: null
16-06-13 22:43:13.918;WebSocket;7: Read frame from websocket: 377, opcode:TEXT_FRAME
data: =,6GiGGV7C6_TfPHg\~\c

これは、受信したフレームの別の例ですが、少し形式が正しくありません!? これは TCP/TLS 接続でどのように可能ですか???:

17-06-13 09:42:37.510;WebSocket;7: Read frame from websocket: 15, opcode:TEXT_FRAME
data: "kep-aiveY:"d613Nb2-N24eV463K-808-fJb30I9e3M02

{"keep-alive":"[UUID]"} と読むことになっています

一方、さらにテストを行ったところ、-1 を受信した後も読み続けると、10 回中 9 回は機能することがわかりました。したがって、フレームの途中まで読んで -1 を受け取ったとしても、ソケットが閉じているかどうかを何らかの方法でテストする必要があります。そうでない場合は、バッファをいっぱいにしていきます。そうするために、ソケットが SSLSocket である次のコードを使用します。

public static int readFully(Socket socket, InputStream is, byte[] buffer, int off, int len) throws IOException
{
    int read = 0;
    while(read < len)
    {
        int b = is.read();
        if(b < 0)
        {
            Logger.log(TAG, "readFully read returned: " + b + " testing if connection is reset or closed.", Logger.WARNING);
            if(socket.isInputShutdown())
            {
                throw new IOException("InputStream closed before data could be fully read! (readFully read returned -1 and socket.isInputShutdown() is true");
            }
        }
        else
        {
            buffer[off + (read++)] = (byte) b;
        }
    }
    return read;
}

まだ 100% 正しいわけではありませんが、少なくとも以前よりも信頼性の高い結果が得られます。

4

1 に答える 1

0

socket.in.read(buffer,off,len) から予期しない -1 の結果が返されました

このメソッドを呼び出す前に、すでに EOS (ストリームの終わり) に達しています。

これはフレームの途中でも発生します。

TCP には「フレーム」のようなものはありません。アプリケーション メッセージの途中で発生した場合は、アプリケーション プロトコル エラーが発生しています。

通常、ストリームの終わりであるため、-1 を受信するとすぐにソケットを閉じます。

正しい。

ただし、接続のリセットでも発生する可能性があることに注意しました

いいえ、そうではありません。その場合、リセットを検出できなかった可能性があります。その発言は自己矛盾している。

私のテストでは、読み取り後に貴重なデータを返すソケットが -1 を返すという多くのケースに遭遇しました。

いいえ、していません。ソケットは、最初に -1 を返した後は何も返すことができません。どこかで -1 を無視しない限り、「貴重な」データは言うまでもなく、データをまったく取得することはできません。

私の問題は、そのような場合にソケットからスクランブルされたデータを取得することがある場合に発生します。

あなたがやっているように、-1を無視する場合にのみ。

もう 1 つの問題は、フレームを配信できないときに相手側に通知されないことです。

もちろんそうではありません。反対側に通知を配信できれば、パケットを配信できます。これも意味がありません。相手側がパケットを配信できなかったとき通知を受け取らないことを意味する場合は、TCP 送信が非同期であるという事実に反対しているため、通常、それを引き起こした送信で送信エラーが発生することはありません。後で送信されます。送信ごとの確認が必要な場合は、それらをアプリケーション プロトコルに組み込む必要があります。

では、TCP/SSL は何の役に立つのでしょうか。

TCP は信頼できるデータ ストリーム プロトコルであり、SSL は安全で信頼できるデータ ストリーム プロトコルです。それが彼らの使い方です。

Javaでwebsocketフレームを転送するための信頼できない接続と考える必要がある場合?

どちらも信頼できないものではありません。

read が -1 を返した後に何をすべきかを誰かが知っていることを願っています。

ソケットを閉じます。

その間、さらにテストを行ったところ、-1 を受信した後も読み続けると、10 回中 9 回は機能することがわかりました。

いいえ、そうではありません。1000回の1000回は-1を返し続けます。ここに表示されているのは、コード内の他のバグの影響だけです。

したがって、フレームの途中まで読んで -1 を受け取ったとしても、ソケットが閉じているかどうかをテストする必要があります。

できません。ソケット閉じていません。証明: 例外を取得せずに読み取っただけです。-1 を返す以外に、接続が閉じているかどうかをテストすることもできません。read()

私は今使用しています:socket.isInputShutdown()。

無意味。これは、自分のソケットを呼び出したかどうかを示します。Socket.shutdownInput()接続の状態についてしゃがんだことはわかりません。読み取りまたは書き込み以外に、それを実行できる TCP API はありません。

そうでない場合は、バッファをいっぱいにしていきます。

つまり、返される -1 を無視してガーガベを読んでいread()ます。

そうするために、ソケットが SSLSocket である次のコードを使用します。

なんで?DataInputStream.readFully()もう存在している。再実装しても役に立ちません。

if(b < 0)
{
    Logger.log(TAG, "readFully read returned: " + b + " testing if connection is reset or closed.", Logger.WARNING);
    if(socket.isInputShutdown())

この時点でSocket、入力のためにシャットダウンしているかどうかは 100% 関係ありません。read()-1 が返されました。これは、ピアが接続を閉じたことを意味します。限目。

    {
        throw new IOException("InputStream closed before data could be fully read! (readFully read returned -1 and socket.isInputShutdown() is true");
    }

これはすべてナンセンスです。

}
else
{
    buffer[off + (read++)] = (byte) b;
}

-1,ここでは0xff,、バッファにある下位バイトを追加しています。これもナンセンスです。

于 2013-08-14T10:06:07.003 に答える