【问题标题】:socket.io connecting from Firefox and Safari but not from Chrome. Also exhibiting weird behaviour with browser refreshsocket.io 从 Firefox 和 Safari 连接,但不是从 Chrome。浏览器刷新也表现出奇怪的行为
【发布时间】:2021-12-18 10:06:09
【问题描述】:

我正在整理一个用于 nodejs 的 socket.io 实现。

该应用程序在大多数使用各种浏览器的设备上运行良好,但在某些设备上,Chrome 无法连接到套接字服务器,引发此控制台错误:

WebSocket connection to 'wss:<mydomain.com>:3000/socket.io/?EIO4&transport=websocket' failed: websocket.js 88
    doOpen    @websocket.js:88
    open      @transport.js:46
    open      @socket.js:197

...以及更多类似的行。 (为了这篇文章,我已将我的实际域名更改为 。)

奇怪的是,至少在一台设备上,Firefox 和 Chrome 都可以正常连接。但在某些设备上,只有 Firefox 会连接,而 Chrome 会抛出上述错误。

更奇怪的是,在 Chrome 浏览器无法连接到套接字服务器的设备上,如果我手动输入 https://:3000/socket.io/EIO=4&transport=polling 到地址栏,我得到了预期的输出:

0{"sid":"j53jSJFo3j_0393mc0sjai4209", "upgrades": ["websocket"], "pingInterval":25000, "pingTimeout":200000}

现在这里真的很奇怪:在无法连接到套接字服务器的设备上,如果我在实例化 io 服务器连接时删除 io 选项,然后刷新客户端浏览器,它抛出一个 CORS 错误——这是意料之中的——但是如果我撤消代码更改并再次刷新客户端浏览器,它开始工作

所以它开始无法在 Chrome 中工作,但如果我更改代码然后将代码改回,它就会开始工作,因为它在第一次/页面加载时无法工作。

这是服务器代码:

const { Server }     = require("socket.io");
const express = require('express');
const app = express();
const https = require('https');
const server = https.createServer({
    key: fs.readFileSync('<privkey_location>'),
    cert: fs.readFileSync('<cert_location>'),
    ca: fs.readFileSync('<chain_location>'),
    requestCert: true,
    rejectUnauthorized: false
},app);
global.io = new Server(server);

server.listen(3000, () => {
    console.log('listening on *:3000');
});

io.on('connection', (client) => {
    client.emit('hlo');
});

...和客户端页面:

<script src="https://www.netwaffles.com:3000/socket.io/socket.io.js"></script>
<script type="text/javascript">

var srv = io('<mydomain.com>:3000' , { transports : ['websocket'], secure: true });

srv.on('hlo', function() { alert('Connected.'); });

</script>

这样在大多数设备/浏览器上都可以正常工作。它甚至可以在某些设备上的 Chrome 中使用。

但是在 Chrome 浏览器最初无法连接的设备上,如果我更改此行:

var srv = io('<mydomain.com>:3000' , { transports : ['websocket'], secure: true });

...到这个:

var srv = io('<mydomain.com>:3000');

...并刷新浏览器,它仍然无法连接,除了现在错误是 CORS 错误(正如预期的那样)。

但是如果我把那行改回这个:

var srv = io('<mydomain.com>:3000' , { transports : ['websocket'], secure: true });

...然后我再次刷新 Chrome 浏览器,它在尝试几秒钟后连接到套接字服务器,并且该应用程序通常开始正常工作,就像它从一开始就在其他设备上一样正常工作。

这在我看来是香蕉。

如果我在客户端浏览器工作后关闭它,然后打开浏览器以开始一个新的会话,当我加载页面时它又回到不工作状态。我可以在不开始工作的情况下刷新页面一百次,但是如果我执行上面的繁琐操作(从代码中删除 io 选项,刷新客户端浏览器,然后撤消代码更改并使用原始代码再次刷新客户端浏览器代码)它开始工作并继续工作,直到我再次关闭浏览器并开始一个新会话。

同时在大多数设备上,它第一次运行良好,没有任何问题,无论使用什么浏览器。

关于可能导致此问题的原因以及如何使 socket.io 在 Chrome 中可靠工作的任何想法?

【问题讨论】:

    标签: javascript node.js google-chrome sockets


    【解决方案1】:

    我想出了一个解决方法,以防其他人遇到这个问题。

    我不认为这是一个适当的修复,因为它没有解决问题的原因,但它似乎确实可以可靠地消除症状(因为它使页面在第一次页面加载时在 Chrome 上正确加载)。

    解决方法只是一个厚颜无耻的小预填充,以模拟 OP 中的 edit-code-and-reload-page-then-undo-code-edit-and-reload-again rigmarole。基本上我只是改了这​​行代码:

    srv = io('<mydomain>:3000' , { transports : ['websocket'], secure: true });
    

    ...到这个:

    var srv = {};
    if (!!window.chrome) {
        srv = io('<mydomain>:3000');
    }
    srv = io('<mydomain>:3000' , { transports : ['websocket'], secure: true });
    

    如果有人偶然发现这篇文章,他对 socket.io 有更透彻的了解,并且可以解释为什么 Chrome 需要这种解决方法,以及理想情况下如何正确解决问题而不是回避它,那就太好了!

    与此同时,这种变通办法似乎使事情奏效了。

    【讨论】:

      猜你喜欢
      • 2014-08-22
      • 2020-04-25
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2015-07-08
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多