【问题标题】:Is there anyway to prevent TCP from merging packets on NodeJS?有没有办法阻止 TCP 在 NodeJS 上合并数据包?
【发布时间】:2020-03-13 07:06:12
【问题描述】:

我正在做一个学校项目来实现一些算法,我可以通过根据数据包丢失增加或减少来动态改变从客户端发送到服务器的数据包速率。

问题是它只能在每次发送 4 个数据包之前工作,然后,它开始合并数据包并将它们一起发送,所以我无法确定是否有数据包丢失。

无论如何我可以阻止 TCP 执行该行为吗?

客户端代码:

const net = require('net')

const PORT = 8550
const HOST = '127.0.0.1'

const client = new net.Socket()

client.setTimeout(1000)

let windowSize = 1
let sentPackets = 0

client.on('error', () => {
  console.log('Finishing connection...')
  process.exit()
})

client.connect(PORT, HOST, () =>
  console.log('Connected to ' + HOST + ':' + PORT)
)

client.on('connect', () => {
  sendPackets()
})

client.on('data', data => {
  sentPackets++

  if (sentPackets >= windowSize) {
    windowSize *= 2
    sentPackets = 0
    sendPackets()
  }
})

const sendPackets = () => {
  for (let i = 0; i < windowSize; i++) {
    const message = (i + 1).toString()

    client.write(message, err => {
      if (err) console.log(err)
    })
  }
}

client.on('timeout', () => {
  windowSize /= 2
  sentPackets = 0
  sendPackets()
})

服务器代码:

const net = require('net')

const PORT = 8550
const HOST = '127.0.0.1'

const server = net.createServer()

server.on('error', err => console.log(error.toString()))

server.listen(PORT, HOST, () =>
  console.log('Servidor listening to ' + HOST + ':' + PORT)
)

server.on('connection', socket => {
  socket.on('data', data => {
    console.log('Received: ' + data.toString())

    socket.write(data)
  })

  socket.on('error', err => {
    console.log(err.toString())
  })
})

我知道它收集数据包是因为服务器的以下输出:

收到:1
收到:1
收到:2
收到:1
收到:234

然后它遵循相同的顺序。

【问题讨论】:

  • TCP 连接通常被认为是来自服务器端和客户端的流(下面它确实使用 IP 数据包)。为了分隔更高级别/应用程序级别的数据包,您可以使用一个标头来指示每个数据包的长度,或者使用某种分隔符。你可以看看stackoverflow.com/questions/22414353/… 来获得灵感,这似乎有点相同的挑战。
  • 使用 TCP,您无法直接控制您发送的数据如何分组到数据包中或确切地如何传递。如果您需要将其分离成某种类似的单元,那么您必须在应用程序级别执行此操作,并在数据中进行某种划分,您可以在交付时对其进行分类,或者使用 TCP 之上的协议(如 webSocket)或为你做的 socket.io。
  • 仅供参考,对于发送数据,TCP 有一个内置的延迟过程,当您发送一小段数据时,它会等待很短的时间来查看是否还有更多数据,因此 TDP 可以将它们组合成一个普通的数据包。您可以在 nodejs 中使用 socket.setNoDelay() 禁用它。
  • 但是,即使您使用setNoDelay(),您也不能指望数据包到达的部分与您发送它们的部分完全相同。这就是 TCP。 TCP 允许将小块数据合并成一个更大的数据包(这通常会提高效率)。

标签: node.js sockets tcp


【解决方案1】:

先生,

TCP 是面向流的协议。什么意味着它正在发送和接收字节流。不保留写入有效载荷的边界。更重要的是TCP 已经在其堆栈中内置了拥塞控制。

对于您的项目,这不是一个好的传输协议选择,除非您正在实现自己的TCP/IP 堆栈版本。因为操作系统堆栈中的拥塞控制实现是保持自己的发送和接收窗口,并在需要时调整传输速率。它会干扰您从应用程序控制它的意图。

根据您提供的示例代码,您似乎需要保留消息边界的能力。您可以使用普通的旧 UDP 来实现这一点。还有其他协议,例如SCTPDCCP,但它们提供拥塞控制。也可以使用HTTP 之类的应用层协议或实现序列化机制(即protobuf),但它仍将通过TCP 连接进行操作。

我建议你使用UDP。它不可靠,只是尽力而为。但是,您可以实现自己的可靠性机制,您可以将其与顶部的传输控制机制连接起来。如需灵感,请阅读 TCPDCCPSCTP 的运作方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-18
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多