3

Java で websocket サーバーをゼロから開発しました。JavaScript クライアントがブラウザで実行されています。

function connectToServer() {
    connection = new WebSocket("ws://" + document.domain + ":8351");       
    connection.onopen = function () {
    };

    connection.onmessage = function (e) {
        handleServerResponse(e.data);
    };
}

メッセージ (json) が 65535 バイトに達するまでは問題ありません。次に、ソケットが閉じられます(クライアントまたはサーバーが接続を閉じるかどうかはわかりません。

ブラウザー コンソール (いくつかのブラウザーを試した) で、次のように表示されます。ページの読み込み中に ws://localhost:8351/ への接続が中断されました。

サーバー側では、次のように表示されます: java.net.SocketException: Connection reset at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)

したがって、問題がハンドシェイクにある場合、またはサーバーでフレームを正しく構築せずにクライアントが接続を閉じた場合、またはストリームに間違ったバイトを書き込んでいて Java io がソケットを閉じた場合。

私のコード(サーバー):

1) ハンドシェイク(サーバー応答)

  String _01 = "HTTP/1.1 101 Switching Protocols\r\n";
  String _02 = "Upgrade: websocket\r\n";
  String _03 = "Connection: Upgrade\r\n";
  String _04 = "Sec-WebSocket-Accept: " + responseKey + "\r\n";
  String _05 = "Content-Encoding: identity\r\n";

2) フレームの構築 (大きなメッセージは別のフレームに分割する必要がありますか?)

public static byte[] buildFrame(String message)
{
    int length = message.length();
    int rawDataIndex = -1;
    if (length <= 125)
        rawDataIndex = 2;
    else if (length >= 126 && length <= 65535)
        rawDataIndex = 4;
    else
        rawDataIndex = 10;
    byte[] frame = new byte[length + rawDataIndex];
    frame[0] = (byte)129;
    if (rawDataIndex == 2)
        frame[1] = (byte)length;
    else if (rawDataIndex == 4)
    {
        frame[1] = (byte)126;
        frame[2] = (byte)(( length >> 8 ) & (byte)255);
        frame[3] = (byte)(( length      ) & (byte)255);
    }
    else
    {
        frame[1] = (byte)127;
        frame[2] = (byte)(( length >> 56 ) & (byte)255);
        frame[3] = (byte)(( length >> 48 ) & (byte)255);
        frame[4] = (byte)(( length >> 40 ) & (byte)255);
        frame[5] = (byte)(( length >> 32 ) & (byte)255);
        frame[6] = (byte)(( length >> 24 ) & (byte)255);
        frame[7] = (byte)(( length >> 16 ) & (byte)255);
        frame[8] = (byte)(( length >>  8 ) & (byte)255);
        frame[9] = (byte)(( length       ) & (byte)255);

    }
    for (int i = 0; i < length; i++)
        frame[rawDataIndex + i] = (byte)message.charAt(i);
    return frame;
}

3)バイトをソケットに書き込む(socket.setSendBufferSizeとBufferedOutputStreamを試しましたが、何も役に立ちません)

socket.getOutputStream().write(byteMessage);
socket.getOutputStream().flush();

誰かが同じ問題に遭遇しましたか? どんな助けでも大歓迎です!

4

2 に答える 2

4

私は答えるのが少し遅いことを知っています...しかし、とにかく、私は同じ問題とこのコードに直面しました:

    frame[1] = (byte)127;
    frame[2] = (byte)(( length >> 56 ) & (byte)255);
    frame[3] = (byte)(( length >> 48 ) & (byte)255);
    frame[4] = (byte)(( length >> 40 ) & (byte)255);
    frame[5] = (byte)(( length >> 32 ) & (byte)255);
    frame[6] = (byte)(( length >> 24 ) & (byte)255);
    frame[7] = (byte)(( length >> 16 ) & (byte)255);
    frame[8] = (byte)(( length >>  8 ) & (byte)255);
    frame[9] = (byte)(( length       ) & (byte)255);

動作します。ここでの問題は、変数の「長さ」が 32 ビットの int であることです。また、8バイトでビットシフトを実行しているため、メモリからランダムデータが取得されます。変数の「長さ」を 64 ビット長として定義すると、機能します。

long length = (long)message.length();

私にとって完璧に機能しました。

理解したい方の参考になれば幸いです。

于 2014-07-30T17:40:28.563 に答える