【问题标题】:Writing data to a socket in Node将数据写入 Node 中的套接字
【发布时间】:2012-08-20 07:27:03
【问题描述】:

写入套接字时,我得到了一个奇怪的结果。我用客户端和服务器写了一个简单的实验:

server.js

var net = require('net');
net.createServer(function (connection) {
  connection.on('data', function (data) {
    console.log('data: ' + data);
  });
}).listen(1337);

client.js

var net = require('net');
var client = net.connect({port: 1337}, function () {
  var i = 0;
  function send() {
   client.write('a');
    if (++i < 100) {
      process.nextTick(send);
    } else {
      client.end();
    }
  }
  send();
});

我希望服务器显示 100 行 data: a,但我最终得到的 data: aaaaaaa 行数较少。有socket.setNoDelay()这似乎是我想要的,但它似乎没有任何效果。

我错过了什么?

非常感谢,

【问题讨论】:

    标签: node.js


    【解决方案1】:

    TCP 协议只发送您在套接字中写入的字节。它们不会被分成消息,这取决于你。如果您想获得 100 行 a,那么您必须定义 100 条单独的消息,并为它们选择一个分隔符。通常人们通过\r\n分隔发送到TCP套接字的消息。

    因此您需要将服务器更改为

    var net = require('net');
    net.createServer(function (connection) {
      connection.on('data', function (buffer) {
        var data = buffer.toString();
        if (data.indexOf('\r\n') > -1) { // If there's more than one line in the buffer
            var lines = data.split('\r\n'); // Split the lines
            var i = lines.length;
            while (i--) { // This will read your lines in reverse, be careful
                console.log(lines[i]);   // Print each line
            }
        } else {
            console.log(data); // If only one line came through, print it
        }
      });
    }).listen(1337);
    

    和你的客户

    var net = require('net');
    var client = net.connect({port: 1337}, function () {
      var i = 0;
      function send() {
       client.write('a\r\n'); // Notice the \r\n part. This is what will help you separate messages on the server
        if (++i < 100) {
          process.nextTick(send);
        } else {
          client.end();
        }
      }
      send();
    });
    

    然后我相信你会得到 100 行 a

    This module 也提供了一种非常有趣的方法,当然ZeroMQ 也会在这方面大放异彩,因为它已经有一个很好的协议,可以将东西放入信封并发送。

    同样有趣但超出了您的问题范围,您发送到一侧套接字的消息将不会以相同的顺序到达服务器。如果您将发送功能更改为

      function send() {
        if (++i < 100) {
          client.write('a'+i+'\r\n');
          process.nextTick(send);
        } else {
          client.end();
        }
      }
    

    您可以看到它们不是按照您发送它们的顺序到达的。

    “TCP 协议仅发送您在套接字中写入的字节”我的意思是,如果您执行socket.write("1"); socket.write("2"),您将在服务器上收到"12",因为那是您在套接字上写入的内容。您必须通过某种方式明确分隔您的消息,以便服务器可以知道消息何时开始以及何时结束。

    关于是否按顺序接收东西,您会注意到,如果您删除 process.nexTick 并让您的客户喜欢:

    var net = require('net');
    var client = net.connect({port: 1337}, function () {
      var i = 100;
      while (i--) {
        client.write('a'+i+'\r\n');
      }
    });
    

    你会在服务器上收到两条消息(至少我收到了):第一个数字是 83 - 99,然后是 0 - 82,尽管它们是按顺序写的。

    这是因为 TCP 以某种神奇的方式将其拆分为数据包。第一个包裹实际上比第二个大,所以它最后到达那里。当然,您可以在 wikipedia 页面中阅读有关 TCP 工作原理的更多信息,this video 可能会比您需要听到的内容更多,但了解您正在使用的所有内容会很好。

    【讨论】:

    • 非常感谢您的详细回答。但我想现在我比以前更困惑了。我不明白您所说的“TCP 协议只发送您在套接字中写入的字节”是什么意思。似乎 Node 保留了一个缓冲区列表,并根据我不知道它们可能是什么的条件在某个时候发送它们。这是因为 TCP 协议是如何定义的吗?你能指点我一些文学作品吗?此外,每当我尝试发送 i 的值时,我总是按顺序得到它。我希望 Node 能够处理这个问题,否则你怎么能pipe() 什么?
    • 哦!我现在得到第一部分。非常感谢!我会看视频:D
    • > 这是因为 TCP 以某种神奇的方式将其拆分为数据包。 这听起来不对。 TCP 的重点是在到达混乱的情况下以正确的顺序重新组装数据包。你刚才描述的是UDP,它不关心顺序。
    猜你喜欢
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 2017-06-14
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多