【问题标题】:getting the reason why websockets closed with close code 1006获取关闭代码 1006 关闭 websocket 的原因
【发布时间】:2013-10-18 17:00:09
【问题描述】:

我想了解 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 的控制台上,原因仍然是“”。

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

【问题讨论】:

  • 我认为这是因为服务器如何处理连接/断开连接的事件。我不能肯定地说,但连接关闭也需要在服务器上正确处理代码。尝试覆盖服务器上内置的 On Connected /Disconnected 方法并查看。我的假设只是你正在关闭它,但服务器没有正确关闭,因此没有转发正确的关闭响应。

标签: javascript websocket


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

  • Joakim,谢谢,非常详细的分析器。如果我使用sok.onerror=function (evt) {console.log(evt);},细节就没有那么多了。甚至没有reason 之类的。所以,根本没有选择吗?我只是给用户看,something is wrong, or not connencted?不是很人性化,如果用户能看到“你不能删除,数据库限制的原因”就好了。有什么选择吗?谢谢
  • 你应该使用sok.onclose来代替触发close event,它有reasoncode在里面
  • @IhabKhattab 这将是关闭代码特定的,以及关闭发生时。拥有sok.onclose 将适用于许多路径,但并非所有路径。尤其是糟糕的协议,糟糕的握手错误(比如某些可能导致关闭代码1006 的情况)。这在未来会改变吗?大概。但是当这个答案写出来时,它是真的。
  • @JoakimErdfelt 抱歉,我正在回复@slevin 的问题,即当他使用onerror 时,他没有返回reason 我指出此属性codereason 特定于@987654343 @ 事件不是 error 事件。所以对他来说最好改用onclose,我错过了什么吗?
  • 在我的情况下,同样的 1006 错误即将到来,但这发生在 Chrome、Firefox 等的情况下,而不是在 iOS 设备的 Opera 或 Safari 的情况下。如果有人有想法,请帮助我,stackoverflow.com/questions/30799814/…
【解决方案2】:

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

我在nginx 中将其更改为 24h,它解决了问题

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

【讨论】:

  • 谢谢!这是我的情况下出现 1006 错误的原因。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

    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

    【讨论】:

    • npm 包呢? :-)
    • @Piranna 继续。 ;)
    • websocket-close-codes npm 包有代码。
    • @whistling_marmot 只在一个方向(为了任何合理的效率)。
    • @Andrew 您可以从单词中获取数字 - wsCloseCodes['PolicyViolation'] - 或者从数字 wsCloseCodes[1008] 中获取单词
    【解决方案5】:

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

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

    更新:哦,天哪,我在这个答案之后实现了几十个基于 websocket 的应用程序,并且每 5 秒 PINGING FROM CLIENT 是保持与服务器连接的正确方法(我不知道我的请注意我建议从服务器 ping)

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

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

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

        我们有一个负载平衡器,而浏览器发送的字节数超过握手期间协商的字节数,导致负载平衡器终止连接。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-18
          • 1970-01-01
          • 2016-11-30
          • 2019-05-25
          相关资源
          最近更新 更多