112

我想知道 websockets 关闭的原因,所以我可以向用户显示正确的消息。

我有

sok.onerror=function (evt) 
     {//since there is an error, sockets will close so...
       sok.onclose=function(e){
           console.log("WebSocket Error: " , e);}

代码始终为 1006,原因始终为“”。但我想区分不同的关闭原因。

例如,命令行给出了一个错误原因:“你不能删除它,因为数据库不会让你”。但在 Chrome 的控制台上,原因仍然是“”。

还有其他方法可以区分不同的关闭原因吗?

4

7 回答 7

151

关闭代码1006是一个特殊代码,表示连接被浏览器实现异常(本地)关闭。

如果您的浏览器客户端报告关闭代码1006,那么您应该查看websocket.onerror(evt)事件以获取详细信息。

但是,Chrome 很少会1006向 Javascript 端报告任何关闭代码的原因。这可能是由于 WebSocket 规范中的客户端安全规则防止滥用 WebSocket。(例如使用它来扫描目标服务器上的开放端口,或为拒绝服务攻击生成大量连接)。

请注意,1006如果在 HTTP 升级到 Websocket 期间出现错误,Chrome 通常会报告关闭代码(这是技术上“连接”WebSocket 之前的步骤)。由于错误的身份验证或授权,或错误的协议使用(例如请求子协议,但服务器本身不支持相同的子协议),甚至尝试与不是 WebSocket 的服务器位置通信(例如尝试连接到ws://images.google.com/)

从根本上说,如果您看到关闭代码1006,则说明 WebSocket 本身存在一个非常低级别的错误(类似于“无法打开文件”或“套接字错误”),这并不是真正针对用户的,因为它指向一个低级别问题使用您的代码和实现。修复您的低级问题,然后当您连接时,您可以包含更合理的错误代码。您可以根据项目的范围或严重性来实现这一点。示例:信息和警告级别是项目特定协议的一部分,不会导致连接终止。报告严重或致命消息时,也使用项目的协议来传达所需的尽可能多的细节,然后使用 WebSocket 关闭流的有限功能关闭连接。

请注意,WebSocket 关闭代码的定义非常严格,关闭原因短语/消息的长度不能超过 123 个字符(这是有意的 WebSocket 限制)。

但并非全部丢失,如果您只是出于调试原因想要此信息,则关闭的详细信息及其根本原因通常会在 Chrome 的 Javascript 控制台中以相当多的详细信息报告。

于 2013-10-10T20:05:00.603 回答
39

在我和可能@BIOHAZARD 的情况下,它是nginx proxy timeout. 默认情况60下,套接字中没有活动是 sec

我将其更改为 24 小时nginx,它解决了问题

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
于 2019-08-29T08:30:45.607 回答
14

当 Chrome 不符合 WebSocket 标准时,情况似乎就是这样。当服务器发起关闭并向客户端发送关闭帧时,Chrome 认为这是一个错误,并以代码 1006 和无原因消息将其报告给 JS 端。在我的测试中,Chrome 从不响应服务器启动的关闭帧(关闭代码 1000),这表明代码 1006 可能意味着 Chrome 正在报告自己的内部错误。

PS Firefox v57.00 妥善处理了这种情况,并成功将服务器的原因消息传递到 JS 端。

于 2018-11-16T14:45:14.507 回答
10

认为这对其他人可能很方便。孩子们,知道正则表达式很有用。呆在学校。

编辑:把它变成一个方便的花花公子功能!

let specificStatusCodeMappings = {
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
};

function getStatusCodeString(code) {
    if (code >= 0 && code <= 999) {
        return '(Unused)';
    } else if (code >= 1016) {
        if (code <= 1999) {
            return '(For WebSocket standard)';
        } else if (code <= 2999) {
            return '(For WebSocket extensions)';
        } else if (code <= 3999) {
            return '(For libraries and frameworks)';
        } else if (code <= 4999) {
            return '(For applications)';
        }
    }
    if (typeof(specificStatusCodeMappings[code]) !== 'undefined') {
        return specificStatusCodeMappings[code];
    }
    return '(Unknown)';
}

用法:

getStatusCodeString(1006); //'Abnormal Closure'

{
    '0-999': '(Unused)',
    '1016-1999': '(For WebSocket standard)',
    '2000-2999': '(For WebSocket extensions)',
    '3000-3999': '(For libraries and frameworks)',
    '4000-4999': '(For applications)'
}

{
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
}

来源(为简洁起见稍作修改):https ://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes

于 2020-04-18T03:10:36.003 回答
2

在 nginx 代理下使用 Chrome 作为客户端和 golang gorilla websocket 作为服务器时出现错误

并且每隔 x 秒从服务器向客户端发送一些“ping”消息即可解决问题

更新:哦,男孩,我在这个答案之后实现了几十个基于 websocket 的应用程序,每 5 秒从客户端 PING一次是保持与服务器连接的正确方法(当我建议从服务器 ping 时,我不知道我在想什么)

于 2019-08-16T21:30:19.910 回答
0

这可能是您在设备中使用的 websocket URL 不同(您从 android/iphonedevice 访问不同的 websocket URL)

于 2019-09-12T11:41:07.277 回答
0

将此添加为可能的原因之一,而不是回答问题。

我们只影响基于铬的浏览器的问题。

我们有一个负载均衡器,浏览器发送的字节数比握手期间协商的要多,导致负载均衡器终止连接。

TCP 窗口缩放为我们解决了这个问题。

于 2021-10-29T15:35:31.480 回答