当向Node.js tcp套接字发送多条消息时,它们将作为单个消息进行流式传输

Ove*_*d D 14 sockets tcp node.js

为了显示一个简单的例子,我想向node.js tcp socket发送多条消息.我只想在第一条消息完全发送/排出时发送第二条消息.但是,即使在等待调用写回调时,消息似乎也会作为一条消息发送.

以下是一些示例代码:

var net = require('net');

var server = net.createServer();

server.on('connection', function(socket){
  socket.write('First Message', function(){
    socket.write('Second Message')
  })
})

var client = new net.Socket();
client.setEncoding('utf8');

server.listen(9999, function(){
  client.connect(9999);
});

client.on('data', function(data){
  console.log('data received on socket:\n' + data);
});
Run Code Online (Sandbox Code Playgroud)

根据socket.write的node.js文档,"当最终写出数据时,将执行可选的回调参数 - 这可能不会立即执行."

基于此,在我的代码中,第二条消息只应在最终为第一条消息写出数据时发送.

但书面输出是:

socket上收到的数据:

第一条MessageSecond消息

如何让它单独发送这些消息?

Edw*_*rzo 22

您需要为消息定义格式,以便客户端可以确定套接字流中消息的开头和结尾.例如,您可以使用回车符来标记示例中消息的结尾.

然后,您可以使用拆分流在客户端中单独读取消息.

var net = require('net');
var split = require('split');
var server = net.createServer();

server.on('connection', function(socket){
  socket.write('First Message\n', function(){
    socket.write('Second Message\n')
  })
})

var client = new net.Socket();
client.setEncoding('utf8');

server.listen(9999, function(){
  client.connect(9999);
});

var stream = client.pipe(split());
stream.on('data',function(data){
    console.log(data);
});
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,如果您对客户端和服务器上的事件/发送数据包做出反应,则需要在客户端和服务器上进行拆分.好例子! (2认同)

Gre*_*ill 16

TCP不会"单独"发送消息.TCP是一种协议,这意味着当您将字节写入套接字时,您将在接收端以相同的顺序获得相同的字节.没有任何类似"消息边界"或"数据包"的概念.

在您的示例中,当套接字层接受您的数据进行传输时,将调用回调.它并不意味着数据已经发送成功,甚至可以说,它已经离开你的电脑在所有.在回调中,您发送第二条消息,但套接字层将其与第一条消息相结合以提高效率,因为它与TCP无关.

  • @JoeHildebrand:是的,我知道唠叨.这是TCP连接应被视为字节流而不是具有边界的消息的主要原因. (3认同)
  • 这是对的。但是,出于完整性考虑,您可能还想了解TCP的Nagle算法(请参阅https://en.wikipedia.org/wiki/Nagle's_algorithm),出于性能原因,该算法将小写内容汇总为大写内容。您可以使用socket.setNoDelay(https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay)在节点中禁用此功能。您不应依赖此来划定消息边界,部分原因是您无法确定某个“智能”网络设备是否将在您上游进行此操作。 (2认同)