2017-04-06 3 views
0

Java WebSocketサーバを作成していて、クライアント(Chrome Version 57.0.2987.133(64ビット))のオープニングハンドシェイクメッセージを受信しました。下に示された。サーバがペイロードを使い果たしたときにwebsocketプロトコルエラーが発生しました

受信:GET/HTTP/1.1
受信:ホスト:localhostを:6789は
受信:接続:プラグマ:キャッシュなし
受信:のCache-Control:キャッシュなし

受信をアップグレードします が受信:アップグレード:WebSocketを
受信:原産地:http://localhost:8080
受信:秒-のWebSocket-バージョン:13
受信:ユーザーエージェント:Mozillaの/ 5.0(Macintosh版、インテルのMac OS X 10_9_5)のAppleWebKit /537.36(ヤモリ様KHTML)クローム/ 57.0.2987.133サファリ/ 537.36
受付:エンコーディングを受け入れ:gzipで、収縮、SDCH、BR
受付:言語を受け入れ:EN-US、ENを、Q = 0.8
受信:Sec-WebSocket-Key:L1IiUSGijbGmTpthWsebOg ==
受信:Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits

送信:HTTP/1.1 101切り替えプロトコル
送信:アップグレード:WebSocketを
を送信:接続:
が送信アップグレード:秒-のWebSocket-受け入れ:受け入れエンコード:送信L5HXnDJGDMYbWr5gRcQMOwKNf3Q =
GZIPを、デフレート
送信:Sec-WebSocket-Extensions:permessage-deflate; client_no_context_takeover; server_no_context_takeover今

、クライアントがメッセージを送信することができ、それは問題なくそうと私のサーバーは、ヘッダバイト0x81と(フィンで応答した場合に自分のコードが正常にjava.util.zip.Deflaterのを使用してそれらを解凍して... 、圧縮なし、テキスト)、0x5に「hello」のバイト(例として)を入力すると、Chromeのjavascriptのwebsocketクライアントは完全に幸せですが、レスポンスを圧縮しようとすると、クライアントは常にエラーコード1002 「Websocket protocol error」というテキストが表示されます。

DEFLATE

public void sendMessageDeflated(String rxMessage, OutputStream streamOut) { 

    System.out.println("Message back to client is: " + rxMessage); 

    // And then compress the response and send it out. 
    Deflater compressor = new Deflater(Deflater.DEFLATED); 
    try { 
     int headerLength = 2; 
     byte unzippedMsg[] = rxMessage.getBytes("UTF-8"); 
     compressor.setInput(unzippedMsg); 
     compressor.finish(); 
     byte zippedMsg[] = new byte[2048]; // Nasty constant but will have to do for now. 
     int toCompressLength = unzippedMsg.length; 
     int compLength = compressor.deflate(zippedMsg, headerLength, zippedMsg.length - headerLength); 
     compressor.end(); 

     zippedMsg[0] = (byte)0xC1; // FIN bit, compression plus opcode for TEXT MESSAGE 
     zippedMsg[1] = (byte)((byte)0x00 | (byte)compLength); // No mask on return data. 

     streamOut.write(zippedMsg, 0, compLength + headerLength); 

    } catch (IOException ioEx) { 
     // TBD 
     System.out.println("IOException: " + ioEx.toString()); 
    } catch (Exception ex) { 
     // TBD 
     System.out.println("IOException: " + ex.toString()); 
    } 
} 

GZIP

public void sendMessageGZipped(String rxMessage, OutputStream streamOut) { 
    // Do something with the message here... 

    System.out.println("Message back to client is: " + rxMessage); 

    // And then compress the response and send it out. 
    try { 
     int headerLength = 2; 
     byte unzippedMsg[] = rxMessage.getBytes("UTF-8"); 
     int toCompressLength = unzippedMsg.length; 

     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     GZIPOutputStream gzipOut = new GZIPOutputStream(baos); 
     gzipOut.write(unzippedMsg, 0, toCompressLength); 
     gzipOut.close(); 
     byte[] payload = baos.toByteArray(); 

     byte header[] = new byte[32]; 
     header[0] = (byte)0xC1; // FIN bit plus opcode for TEXT MESSAGE 
     header[1] = (byte)((byte)0x00 | (byte)payload.length); // No mask on return data. 

     streamOut.write(header, 0, 2); 
     streamOut.write(payload); 

    } catch (IOException ioEx) { 
     // TBD 
     System.out.println("IOException: " + ioEx.toString()); 
    } catch (Exception ex) { 
     // TBD 
     System.out.println("IOException: " + ex.toString()); 
    } 
} 

私はおそらく圧縮されたテキスト=バイナリが、それはうまくいきませんでしたバイナリ思考のためのオペコードへの切り替えを試みました。私が間違ってやったことは本当にわかりません。この実装には、メッセージをまたがるスライディング圧縮ウィンドウは含まれません。私は、応答ヘッダーがそれを明確にすると思います。感謝の意を受けて助けてください。

答えて

0

私は最終的に、クライアント側のwebsocketコードを作成し、メッセージを膨らませようとしたときにスローされた例外を見て解決しました。それで私はこの投稿につながりました:Java decompressing array of bytesこれはzlibラッパーで圧縮できるかどうかについてDeflateが話しています。したがって、processMessage2の1行を上記の例のコードからこれに変更してください。

 Deflater compressor = new Deflater(Deflater.DEFLATED, true); 

... 'nowrap'をtrueに設定します。

Chromeブラウザクライアントは、ヘッダーにgzipをサポートすると主張しています。もし私がそれを働かせたら、私はここに戻ってその答えを投稿します。

関連する問題