Javascript-服务器发送大响应时,WebSocket客户端未接收onmessage事件

时间:2020-10-29 15:12:36

标签: javascript .net websocket

我正在基于TcpClient和与Javascript客户端通信的NetworkStream创建.net Websocket服务器。握手后,客户端请求服务器执行特定操作,服务器生成响应-到目前为止,这是短的JSON字符串被发送回客户端-并且工作正常。

在我要求发送更大的字符串响应(即200k和更多字节的base64编码图像)后,客户端停止接收响应,并且没有触发onmessage事件。如果我切换并发送简短的json-它可以再次正常工作。

当我发送大数据时:

When sending large data

当我发送简单数据时:

When sending simple data

客户端,我从所有无关的代码中删除了代码(行为保持不变)

try{
    ws = new WebSocket("ws://127.0.0.1:8282");
    ws.binaryType = "arraybuffer";
}
catch(err){
    debugger;
    document.getElementById("message").innerHTML = "Not Connected! " + err;         
};
ws.onopen = function () {
    var jsonRequest = '{"action" : "START_STREAM","timeout"  : 20}';
    ws.send("START_STREAM");
};

在服务器端,我在生成响应后隔离了代码(带有我测试并正确解码的base64编码图像的纯字符串):

 Byte[] frame = CreateFrameFromString(serverResponse);
 networkStream.Write(frame, 0, frame.Count());
 networkStream.Flush();
 clientSocket.Close();
 clientSocket = ServerListener.AcceptTcpClient();
 networkStream = clientSocket.GetStream();

用于初始化服务器线程的代码:

 ServerListener.Start();
 clientSocket = ServerListener.AcceptTcpClient();
 NetworkStream networkStream = clientSocket.GetStream();
 while (true)
    {
     if (!networkStream.DataAvailable)
  ...regular loop/server stuff/handshake etc.

方法CreateFrameFromString在下面。操作码已使用0-10值进行了测试,在所有情况下,行为都是相同的-客户端未捕获任何响应。

 private static byte[] CreateFrameFromString(string message, Opcode opcode = Opcode.Text)
    {
        var payload = Encoding.UTF8.GetBytes(message);

        byte[] frame;

        if (payload.Length < 126)
        {
            frame = new byte[1 /*op code*/ + 1 /*payload length*/ + payload.Length /*payload bytes*/];
            frame[1] = (byte)payload.Length;
            Array.Copy(payload, 0, frame, 2, payload.Length);
        }
        else if (payload.Length >= 126 && payload.Length <= 65535)
        {
            frame = new byte[1 /*op code*/ + 1 /*payload length option*/ + 2 /*payload length*/ + payload.Length /*payload bytes*/];
            frame[1] = 126;
            frame[2] = (byte)((payload.Length >> 8) & 255);
            frame[3] = (byte)(payload.Length & 255);
            Array.Copy(payload, 0, frame, 4, payload.Length);
        }
        else
        {
            frame = new byte[1 /*op code*/ + 1 /*payload length option*/ + 8 /*payload length*/ + payload.Length /*payload bytes*/];
            frame[1] = 127; // <-- Indicates that payload length is in following 8 bytes.
            frame[2] = (byte)((payload.Length >> 56) & 255);
            frame[3] = (byte)((payload.Length >> 48) & 255);
            frame[4] = (byte)((payload.Length >> 40) & 255);
            frame[5] = (byte)((payload.Length >> 32) & 255);
            frame[6] = (byte)((payload.Length >> 24) & 255);
            frame[7] = (byte)((payload.Length >> 16) & 255);
            frame[8] = (byte)((payload.Length >> 8) & 255);
            frame[9] = (byte)(payload.Length & 255);
            Array.Copy(payload, 0, frame, 10, payload.Length);
        }

        frame[0] = (byte)((byte)opcode | 0x80 /*FIN bit*/);

        return frame;
    }

我是否缺少某些内容-协议/缓冲区大小等?在测试时,我注意到使用上述设置,我最多可以发送4250个字符的响应,而无需进行任何修改。一旦达到这个数字,响应就会消失了。

1 个答案:

答案 0 :(得分:0)

经过大量的故障排除后,事实证明我必须以数据包形式发送数据,而不是整体发送数据。我将响应分为几部分(50000个字符),并一一发送给他们,而在客户端,我正在onmessage事件中接收这些消息。发送所有响应块后,我关闭了会话-在客户端触发了从base64流创建映像的操作。