简体   繁体   English

Websocket:发送超过65535字节的消息失败

[英]Websocket: sending messages over 65535 bytes fails

I've developed a websocket server in java from scratch. 我从头开始在java中开发了一个websocket服务器。 The javascript client is running in browser: javascript客户端在浏览器中运行:

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

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

Everything is fine until the messages (json) reach 65535 bytes. 一切都很好,直到消息(json)达到65535字节。 Then the socket is closed (i have not figured out, if client or server closes the connection. 然后套接字关闭(我还没弄明白,如果客户端或服务器关闭连接。

In browser console (tried several browsers) I see: The connection to ws://localhost:8351/ was interrupted while the page was loading. 在浏览器控制台(尝试了几个浏览器)中,我看到:在加载页面时,与ws:// localhost:8351 /的连接被中断。

On server side, I see: java.net.SocketException: Connection reset at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113) 在服务器端,我看到:java.net.SocketException:java.net.SocketOutputStream.socketWrite的连接重置(SocketOutputStream.java:113)

So, if the problem is in handshake or I build the frame incorrectly in server and the client closes the connection or I'm writing the bytes to stream incorrect and the java io closes the socket. 所以,如果问题出在握手中,或者我在服务器中错误地构建了框架,并且客户端关闭了连接,或者我正在编写流不正确的字节,而java io会关闭套接字。

My code (server): 我的代码(服务器):

1) Handshake (server response) 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) Building the frame (Should large messages be broken up to different frames?) 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) Writing bytes to socket (I've tried socket.setSendBufferSize and BufferedOutputStream, nothing helps) 3)将字节写入套接字(我尝试过socket.setSendBufferSize和BufferedOutputStream,没有任何帮助)

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

Has anyone encountered the same problem? 有谁遇到过同样的问题? Any help is welcome! 欢迎任何帮助!

I know it's a bit late for answering... but anyway, i faced the same problem and this code: 我知道回答有点迟了......但无论如何,我遇到了同样的问题和这段代码:

    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);

works. 作品。 Your problem here is that your variable "length" is an int that is 32bits. 你的问题是你的变量“length”是一个32位的int。 And you are performing bit shifting on 8 bytes so you get random data from the memory. 并且您正在执行8个字节的位移,因此您可以从内存中获取随机数据。 If you define your variable "length" as a 64 bits long then it works. 如果将变量“length”定义为64位长,则可以正常工作。

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

worked perfectly for me. 对我来说很完美。

I hope it can help someone who wants to understand. 我希望它可以帮助想要理解的人。

As I suspected, the bit-shifting code, populated over the internet does not work. 我怀疑, 通过互联网填充的位移代码不起作用。

Found the following code ( source ) : 找到以下代码( 来源 ):

 frame[1] = (byte)127;

            int left = length;
            int unit = 256;

            for (int i = 9; i > 1; i--)
            {
                frame[i] = (byte)(left % unit);
                left = left / unit;

                if (left == 0)
                    break;
            }

And it works! 它的工作原理! Although I could not figure out, what's the difference. 虽然我无法弄清楚,但有什么区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM