【问题标题】:Websocket: sending messages over 65535 bytes failsWebsocket:发送超过 65535 字节的消息失败
【发布时间】:2013-07-17 07:40:16
【问题描述】:

我从头开始用 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 在 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();

有人遇到过同样的问题吗?欢迎任何帮助!

【问题讨论】:

  • “连接重置”表示当您尝试发送数据时,远程端关闭了连接。你用什么做客户端?它是否允许超过 64k 数据的数据包?
  • 这是一个 javascript 客户端(更新了问题)我可以以某种方式将其配置为接受大消息吗?

标签: java websocket


【解决方案1】:

我知道回答有点晚了...但无论如何,我遇到了同样的问题,这段代码:

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

非常适合我。

希望对想了解的人有所帮助。

【讨论】:

  • 谢谢,这对我很有帮助!
【解决方案2】:

正如我所怀疑的,位移代码populated over the internet 不起作用。

找到以下代码(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;
            }

而且它有效! 虽然我不知道,但有什么区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-02
    相关资源
    最近更新 更多