【问题标题】:Stop tcp packets from concatenating停止连接 tcp 数据包
【发布时间】:2016-02-16 08:10:12
【问题描述】:

我有两个发送 tcp 包的应用程序,都是用 python 2 编写的。当客户端向服务器发送 tcp 数据包的速度太快时,数据包会被连接起来。有没有办法让 python 只从套接字恢复最后发送的包?我将用它发送文件,所以我不能只使用某些字符作为数据包终止符,因为我不知道文件的内容。

【问题讨论】:

  • 这不是 TCP 的工作原理。
  • 正如许多人所建议的那样,所谓的 length-prefixing 是要走的路。我不使用 Python,但我可以毫无问题地从我的程序发送文件 - 它对它发送的每个“数据包”或文件部分使用长度前缀。
  • 我刚刚通过在实际文件之前添加填充和包括文件大小来使所有数据包大小相同。

标签: python sockets tcp


【解决方案1】:

TCP 使用数据包进行传输,但它暴露给应用程序。相反,TCP 层可能决定如何将数据分成数据包,甚至是片段,以及如何传递它们。这通常是由于底层网络拓扑而发生的。

从应用程序的角度来看,您应该将 TCP 连接视为八位字节流,即您的数据单位是字节,而不是数据包。 p>

如果您想传输“数据包”,请使用面向数据报的协议,例如 UDP(但请注意,此类数据包有大小限制,使用 UDP 您需要自己处理重传),或者手动包装它们.例如,您始终可以通过 TCP 先发送数据包长度,然后再发送有效负载。另一方面,首先读取大小,然后您知道需要跟随多少字节(请注意,由于碎片,您可能需要多次读取才能获得所有内容)。在这里,TCP 将负责按顺序发送和重传,所以这更容易。

【讨论】:

  • 我不想使用 UDP,因为它会丢失数据包并以随机排列的方式传递它们。对于文件传输,我不能让这种情况发生
  • 然后按照我概述的方法,先发送一个长度,自己构建“数据包”。因为 TCP 是字节流,而不是数据包。
  • 尝试实施您的这种方法并给出长度。正如您所提到的,我可能会阅读整个文件并计算大小。它再次遍历整个文件。我想使用sys.getfilesize() 函数,但它给了我另一个结果而不是计算字节并且不起作用。
  • 我解决了最后一个问题。问题是,我一直在测量对象字符串的长度,它比字母多 37 个字节。
【解决方案2】:

TCP 是一种流式传输协议,它不会暴露单个数据包。虽然从流中读取和获取数据包可能在某些配置中有效,但即使对涉及的操作系统或网络硬件进行微小更改,它也会中断。

要解决此问题,请使用更高级别的协议来标记文件边界。例如,您可以在文件前面加上以八位字节(字节)为单位的长度。或者,您可以切换到已经处理此类内容的协议,例如 http。

【讨论】:

    【解决方案3】:

    首先您需要知道数据包是在发送之前还是之后合并的。使用wireshark检查发件人是否正在发送一两个数据包。如果它正在发送一个,那么您的解决方法是在每次写入后调用 flush() 。不知道接收方收到包后是否合并包的答案。

    您可以更改您发送的内容。您可以发送已发送的字节,然后是字节。然后对方就会知道要读取多少字节。

    【讨论】:

    • 你的意思是我应该在我的信息中添加一些内容以便我知道结尾在哪里?如果我要发送的文件中出现相同的字节序列怎么办?
    • 这是我的第二个答案。如果你“知道”你将发送 4 个字节大小,然后是那么多字节,重复循环直到 0 或 EOF。那么这 4 个字节将始终被解释为一个大小。使用 struct 将整数转换为 4 字节的网络顺序。 flush() 答案不需要对您的数据包进行任何更改。
    • 是的,但我不认为python中的TCP套接字实现了flush功能。
    【解决方案4】:

    通常,TCP_NODELAY 会阻止这种情况。但是在极少数情况下您需要将其打开。少数有效的应用程序之一是 telnet 风格的应用程序。

    您需要的是 tcp 连接之上的协议。将 TCP 连接视为管道。你把东西放在管道的一端,然后从另一端取出。如果两端没有协调,您不能只通过它发送文件。你已经认识到你不知道它有多大以及它在哪里结束。这是你的问题。协议会处理这个问题。你没有协议,所以你写的东西永远不会健壮。

    你说你不知道长度。获取文件的长度并在标头中传输,然后是字节数。

    例如,如果标头是长度为 64 位,那么当您在服务器端收到标头时,您会读取 64 位数字作为长度,然后继续读取,直到文件末尾应该是长度。

    当然,这非常简单,但这就是它的基础。

    事实上,您不必设计自己的协议。您可以上网并使用现有协议。比如 HTTP。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-04
      • 2019-11-30
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      • 2019-04-30
      • 2011-07-23
      相关资源
      最近更新 更多