节点JS Fork TCP客户端

时间:2019-12-17 13:30:50

标签: javascript node.js networking tcp fork

我对在Node JS中分叉TCP客户端有疑问。这是场景。

  1. 客户端将连接到服务器(建立?)。
  2. 客户端会将第一条消息写入服务器。
  3. 客户端会将第二条消息写入服务器。
  4. “写入”方法将无限循环,延迟时间为5秒。
  5. 将分叉1-4点,并以8秒的延迟创建一个新的TCP连接(与以前不同)。

到目前为止,这是我的方法。

// tcp_client.js

const cluster = require('cluster')

if (cluster.isMaster) {
  for (let i = 0; i < 2; i += 1) {
    setTimeout(() => {
      cluster.fork()
    }, 8000) // I expect this will delay between one and another fork
  }
} else {
  console.log(`Connected on ${process.pid}`)
  require('./sender').send()
}
cluster.on('exit', (worker) => {
  console.log('server',`Worker %d died :( ${worker.id}`);
  cluster.fork();
})
// sender.js

const net = require('net')
const send = () => {
  const client = new net.Socket()
  client.connect(8090, 'localhost', () => {
    const firstMessage = 'first_message'
    const secondMessage = 'second_message'
    const write = function () {
      client.write(firstMessage)
      /*
        The reason why I'm using setTimeout() is because if I write it as
        `client.write(firstMessage)
        client.write(secondMessage)`
        The second message won't be sent. Is there any better methods?
      */
      setTimeout(() => {
          client.write(secondMessage)
      }, 1);
    }

    setTimeout(write, 5000) // I expect this will loop infinitely
  })
}

module.exports = { send }

当我运行代码时,fork不会延迟,消息也不会循环。有什么解决办法吗?谢谢。

1 个答案:

答案 0 :(得分:0)

如果您希望两个叉子相距8秒,则setTimeout()上的时间会有所不同。 setTimeout()没有被阻止,因此您的所有代码都在调度两个setTimeout()-从现在开始持续8秒。这样可以安排一个8秒钟,另一个16秒钟:

// tcp_client.js

const cluster = require('cluster')

if (cluster.isMaster) {
  for (let i = 0; i < 2; i += 1) {
    setTimeout(() => {
      cluster.fork()
    }, (i + 1) * 8000);
  }
} else {
  console.log(`Connected on ${process.pid}`)
  require('./sender').send()
}
cluster.on('exit', (worker) => {
  console.log('server',`Worker %d died :( ${worker.id}`);
  cluster.fork();
})

而且,您的写代码不会循环,因为setTimeout(write, 5000)connect事件处理程序内,而不是write()函数内。因此,当connect事件触发时,它将被调用一次,并且永远不会再次被调用。如果要重复write(),请将其放在write()函数本身中(或使用setInterval())。

// sender.js

const net = require('net')
const send = () => {
  const client = new net.Socket()
  client.connect(8090, 'localhost', () => {
    const firstMessage = 'first_message'
    const secondMessage = 'second_message'
    const write = function () {
      client.write(firstMessage)

      setTimeout(() => {
          client.write(secondMessage)
      }, 1);

      setTimeout(write, 5000) // I expect this will loop infinitely
    }
    write();

  })
}

module.exports = { send }

此外,连续进行两个client.write()调用完全可以,这两个都将被发送。但是,TCP可能会将它们组合到同一个数据包中。 TCP是流协议,而不是基于消息的协议。因此,要描述消息之间的差异,您必须在阅读时解析流。您不应该依赖与发送时完全相同的数据块中到达的数据。可以将其分解为较小的块,也可以将多个单独写入的块组合到同一到达的数据包中。例如,在这种情况下,您可以在每个消息的末尾放置一个\ n,并在读取TCP流时将其用作消息定界符,这样就可以将每个传入的消息分别解析,即使它们是由TCP组合成的。同一包。

或者您可以在TCP之上使用基于消息的协议(例如webSocket),该协议会为您打包和解压缩成不同的消息,并且只会向您传递完成的消息和单独的消息。