socket.io - 数百个请求而不是一个连接

Posted

技术标签:

【中文标题】socket.io - 数百个请求而不是一个连接【英文标题】:socket.io - hundreds of requests instead of one connection 【发布时间】:2018-04-28 01:30:42 【问题描述】:

我从 socket.io 开始创建了一个简单的应用程序,但是当我运行它时,Chrome(在其他浏览器中测试,结果相同)占用了我所有的 CPU 并发出许多请求:

我是套接字的新手,但我确信这不是它应该如何工作的。在浏览器中运行的代码非常简单,它应该只是连接到套接字并将所有接收到的数据记录到控制台:

index.html

<!DOCTYPE html>
<html>
<head>
    <script src="https://cdn.socket.io/socket.io-1.2.0.js" charset="UTF-8"></script>
</head>
<body>
<script type="application/javascript">
    var Sockets = io.connect('http://localhost:4000');
    Sockets.on('Test', function (data) 
        console.log(data);
    );
</script>

</body>
</html>

另外,我的服务器文件如下所示:

server.js

var app = require('express')();
var http = require('http').Server(app);
var bodyParser = require("body-parser");
var io = require('socket.io')(http);
var port = 4000;

http.listen(port, function () 
    console.log('Server running at port ' + port);
);

var urlencodedParser = bodyParser.urlencoded(extended: false);
app.post('/', urlencodedParser, function (req, res) 
    if (!req.body) return res.sendStatus(400);
    var post = req.body;
    io.emit("Test", post.data);
    console.log(post.data);
    res.send('true');
);

io.on('connection', function(socket)
    console.log('a user connected');
    socket.on('disconnect', function()
        console.log('user disconnected');
    );
);

当我运行服务器 node server.js 时,我收到了 Server running at port 4000 消息,一切似乎都很好。但是当我在浏览器中打开 index.html 时,节点控制台会被a user connected 消息发送垃圾邮件。浏览器不是连接一个客户端,而是每秒发出几十个请求。当我关闭浏览器时,有一段时间没有输出,然后节点控制台被user disconnected消息发送垃圾邮件。

此服务器应将所有通过 POST 发送的数据重定向到连接的套接字。当我发出这个 POST 请求时,节点服务器会收到它(我知道是因为它会打印到节点控制台中)。但是socket客户端没有接收到,因为浏览器控制台没有输出(但是浏览器仍然每秒建立几十个新连接。

这里有什么问题?首先我以为我搞砸了,所以我返回并从tutorial I found 复制粘贴代码(不是英语,而是捷克语),但没有任何改变。该教程有很多积极的反馈,所以我的电脑可能有问题。但是什么?

【问题讨论】:

当您说“在我的浏览器中打开 index.html”时,究竟是什么意思?你是直接从文件系统打开吗?您应该通过 Web 服务器打开它,而不是通过文件系统。由于 socket.io 的连接方式,如果 Web 服务器上没有 CORS 配置,它将无法正常工作到跨域服务器。如果您从文件系统打开 index.html,http://locahost:4000 将是一个跨源端点,并且不会让您正确连接。 @jfriend00 我在 phpStorm 中使用“运行”按钮。正如您在屏幕截图中看到的,url 是 localhost:phpstorm'sport/somepath/index.html “运行”按钮的实际作用是什么?我再问一次。 index.html 是从文件系统还是从您的 Web 服务器加载的?它需要从您的 Web 服务器加载。仅供参考,您的网络服务器代码没有显示任何服务 index.html 的方式,所以我怀疑您是从文件系统加载它,这是错误的,也是问题的原因。 @jfriend00 PhpStorm 中的“运行”按钮启动 PhpStorm 中的内部网络服务器。我可以通过输入我在 PhpStorm 中配置的端口的计算机 IP 从局域网中的其他计算机访问该页面,因此必须有一个网络服务器。 【参考方案1】:

我遇到了同样的问题,通过以下示例,客户端使用此 cdn 中的 socket.io 源:https://cdn.socket.io/socket.io-1.2.0.js

每当我尝试运行该文件时,都会创建大量客户端(无论我只是双击 html 文件,还是将它放在 Web 服务器下,如 IIS)。然后我意识到它可能是一个旧版本,我刚刚从这个来源发布了最新版本:https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js

现在一切正常。 希望这会有所帮助

【讨论】:

让客户端和服务器使用相同版本的 socket.io 并且成功了!谢谢 这个答案是什么意思??你拿走了它并做了什么?我打开了链接,它只是代码。我应该把它放在哪里? @Chiaro 我发布的链接是 socket.io 的 CDN。您需要将其包含在您的应用程序中,并针对它进行编码。您可以找到有关如何使用 socket.io google-ing "Real-Time Communications with Socket.IO" 创建实时通信应用程序的示例。选择最适合您的链接。【参考方案2】:

所以为了找出问题所在,我从 socket.io 网站下载了示例套接字聊天。当我运行它时,我遇到了完全相同的错误行为 - 浏览器每秒打开许多套接字连接,而不是保持一个。

所以我删除了 node_modules 文件夹并使用 npm 再次安装这些模块,哇,它成功了。因此,可能是文件在下载过程中损坏或其他任何情况,但这次再次执行相同的过程是可行的。

【讨论】:

【参考方案3】:

您从与您的 socket.io 服务器不同的 Web 服务器运行该页面的配置将无法正常工作。需要进行以下三个更改之一才能使其正常工作:

    您可以通过从与您的 socket.io 相同的服务器加载网页来为网页和 socket.io 连接使用“同源”。这意味着您需要直接从您的 socket.io 网络服务器加载网页。

    您可以将 socket.io Web 服务器配置为接受跨源连接(CORS 连接)。

    您可以将 socket.io 客户端配置为使用 webSocket 直接连接,而无需使用常规 http 请求执行 socket.io 的通常预览。

如果您正在测试您打算真正部署的东西,您不妨将现有的 socket.io 网络服务器作为您的网页服务器,并直接从那里加载网页。


造成这种情况的另一个可能原因是 socket.io 的客户端和服务器版本不兼容。您应该绝对确保您在客户端和服务器上拥有相同版本的 socket.io。如果您从您的 socket.io Web 服务器的/socket.io/socket.io.js 获取客户端 socket.io 库,则客户端版本将自动始终与服务器版本匹配。从 CDN 加载它的方式,你必须手动确保你有相同的版本。

【讨论】:

我不这么认为。请求没有被阻止,节点服务器接受它们,并且在 Chrome 开发者工具的网络选项卡中,它们都被列为 200 OK。出于某种原因,它们只是每秒重复多次。为了确保,我按照this question 启用了CORS,它没有任何区别。 @AdamJežek - 你的架构是错误的,无论如何都不能模仿你在现实世界部署中使用的任何东西。修复架构,我打赌你的问题会消失。 FWIW,我认为这可能是最近版本的 socket.io 中引入的问题。在过去的几周里,我已经看到了几份关于您报告的相同类型行为的报告,并且在 3 年内从未见过。但是,我敢打赌,如果你使用适当的架构,你可以避免它。 @AdamJežek - 为什么你坚持从一个不是你的实际 Web 服务器的服务器加载网页?只需向您的 web node.js 服务器添加一个路由来加载页面并通过该服务器加载它。 @AdamJežek - 我也想知道这是否可能是由于 socket.io 客户端和服务器版本不匹配造成的。我看到您正在手动链接到特定的客户端版本,因此您必须手动确保客户端和服务器是相同的版本。如果您从 socket.io 网络服务器的/socket.io/socket.io.js 加载客户端,那么您每次都会自动获得正确的客户端版本的 socket.io。 我打算让 Apache 服务器为您提供 .php 页面,该服务器将包含连接到同一服务器上 node.js 服务器上的套接字的脚本,只有不同的端口。我在很多网站上都看到过,它很实用。如果您在 php 中运行大型网站,则不必在 node.js 中全部重写,只需将 node.js 添加为第二个服务器,仅用于实时处理。我已经找到了解决方案,它与提供页面无关,甚至当我从文件系统打开页面时它也可以工作。

以上是关于socket.io - 数百个请求而不是一个连接的主要内容,如果未能解决你的问题,请参考以下文章

优化返回大量记录的查询,避免数百个连接。这是一个聪明的解决方案吗?

使用 AFNetworking 同时处理数百个请求

Django 持久数据库连接

Blazor WASM 异常导致数百个额外的套接字和连接异常

具有数百个数据库连接的 MVC 应用程序

将数百个 csv 文件转换为 hdf5 文件