如何防止 Node.js 将套接字消息拆分成更小的块

Posted

技术标签:

【中文标题】如何防止 Node.js 将套接字消息拆分成更小的块【英文标题】:How to keep Node.js from splitting socket messages into smaller chunks 【发布时间】:2011-03-27 02:32:49 【问题描述】:

我有一个聊天程序,它通过 TCP 套接字将 JSON 数据从 Apache/php 推送到 Node.js:

// Node.js (javascript)
phpListener = net.createServer(function(stream)

    stream.setEncoding("utf8");
    stream.on("data", function(txt)
    
        var json = JSON.parse(txt);

        // do stuff with json
    

phpListener.listen("8887", 'localhost');

// Apache (PHP)
$sock = stream_socket_client("tcp://localhost:8887");
$written = fwrite($sock, $json_string);
fclose($sock);

问题是,如果 JSON 字符串足够大(超过 8k 左右),输出消息会被分成多个块,并且 JSON 解析器会失败。 PHP 返回 $written 值作为字符串的正确长度,但数据事件处理程序触发两次或更多次。

我应该将函数附加到不同的事件,还是有办法在事件触发时缓存文本,在重负载下不会屈服于竞争条件?还是我没有想到的其他解决方案?

谢谢!

【问题讨论】:

【参考方案1】:

您应该尝试使用缓冲区来缓存数据,因为 Node.js 倾向于拆分数据以提高性能。

http://nodejs.org/api.html#buffers-2

您可以缓冲所有请求,然后使用存储在其中的数据调用该函数。

【讨论】:

解决方案很好,但不是 Node.js 进行拆分,它是服务器上的操作系统或客户端上的操作系统或两端的调制解调器/路由器或路由器在您的 ISP 或沿途的路由器上。这就是互联网的运作方式。您可以将客户端和服务器上的操作系统配置为使用巨型数据包来减少碎片,但您不能保证网络不会对数据包进行碎片化(当然,除非你们都在同一个 LAN 上)。 嗨,你是对的,大部分时间是操作系统或服务器拆分内容,但 node.js 也会拆分输入请求以提高性能,如文档中所述。我希望 IPv6 的巨型包可以帮助我们避免它,但我的猜测是服务器出于性能原因会不断拆分内容(至少在 Web 上)【参考方案2】:

TCP 套接字不会为您处理缓冲。怎么可能?它不知道您正在使用什么应用层协议,因此不知道什么是“消息”。您可以在其之上设计和实现另一个协议并处理任何必要的缓冲。

但是,Node.js 确实有一个基于 TCP 的内置应用层协议,它会自动为您处理缓冲:http 模块。如果您为此使用 http 模块而不是 tcp 模块,则无需担心数据包碎片和缓冲。

【讨论】:

不,http 模块也不会为您缓冲完整的消息。 Node 是围绕流数据构建的。因为它更有效率。因此,您必须始终进行自己的缓冲,或者使用更高级别的框架来为您完成。

以上是关于如何防止 Node.js 将套接字消息拆分成更小的块的主要内容,如果未能解决你的问题,请参考以下文章

将巨大的(95Mb)JSON 数组拆分成更小的块?

如何将数据访问层分成更小的类

putExtra:我应该如何处理大型数组?数据库或拆分为更小的阵列?

将数组分成更小的连续部分,使 NEO 值最大

如何将结果集拆分为更小的子集?

(转载)RTMP 协议学习总结