26

在客户端/服务器应用程序中,不同长度的文本数据将在客户端和服务器之间来回发送,我应该如何标记正在发送的数据包的结尾?例如,当服务器从客户端接收数据包数据时,服务器如何知道客户端数据包已被完全接收?

更常见的是在数据之前告诉服务器它将接收的数据包的完整长度还是标记数据包的结尾?

有些发送的数据只有几个字符长,有些可能是数千个字符。

4

6 回答 6

37

TCP 提供连续的数据流。TCP 是使用数据包实现的,但 TCP 的全部意义在于隐藏它们。

把它想象成你想在上面画画的墙。墙是砖砌的。砖用砂浆粘在一起,抹灰使墙面光滑。砖块是 IP 数据包,TCP 是石膏。

所以现在你有了光滑的抹灰 TCP 隧道,你想在里面添加一些结构。您想绘制方框,以便您的绘图彼此分开。这就是您想要做的:为您的数据添加一些“管理”结构(图纸周围的框)。

许多协议使用 a 的概念packet,它是一组以固定格式的管理标头开头的数据。标头包含足够的信息来决定数据包的结束位置;例如,它包括数据包长度。HTTP 使用Content-Length标头或(使用 HTTP/1.1)使用“分块传输编码”来做到这一点,其中数据被拆分为一个或多个迷你数据包,每个迷你数据包都有一个简单的标头,其中包含一个迷你数据包长度指示。

另一种方法是有一个特殊的终止序列,它不能出现在“正常数据”中。如果您的数据是文本,那么您可以使用值为零的字节作为终止符。

还有一种方法是使用自终止数据。这是一种结构化的数据,您可以随时知道是否已到达元素的末尾。例如,XML 数据被组织为嵌套的标记对,例如<foo>...</foo>. 当到达结束标记 ( </foo>) 时,您就知道该元素已完成。

于 2010-03-05T21:46:10.327 回答
4

以这样一种方式构建您的数据包,使其在开头包含一个长度字段。

于 2010-03-05T20:36:07.303 回答
4

从 HTTP 中获取线索。

使用终止符序列,或在消息头中的某处指定长度,或使用两者的巧妙组合。

就像 HTTP 一样:标头以 CR-LF-CR-LF 结尾。如果有数据通过标头,则数据长度在标头之一中。

于 2010-03-05T20:40:45.290 回答
4

如果您在开始时对长度进行编码,请当心垃圾。例如,如果您使用 4 个二进制字节作为长度并且某个外部探测器发送了一个 HTTP 请求,那么您最终可能会得到一个巨大的数字并永远等待(更不用说分配一个可能会使您的程序崩溃的缓冲区)。我通过不同的函数发送长度两次并比较它们(例如~len和len xor 0x139AF321)。您还应该设置一个最大值,以防有人主动尝试使您的程序崩溃。如果我的长度不好,我会关闭连接。

如果您的流量已加密,则这超出了 HMAC。

于 2016-11-26T04:25:20.820 回答
3

如果发送者知道长度,那么发送者应该预先提供长度作为固定大小的字段,然后是可变大小的数据。

与尾部标记相比的优势在于接收器可以针对预期的数据量进行优化,例如分配正确大小的缓冲区。例如,基于 TCP/IP 协议的存储与您在 TCP/IP 上的问题相同。在这些情况下,标头提供后续预期数据的长度。

稍后,您可能会在“标题”中找到其他内容。你会很高兴你有一些结构来发展你自己的第 5 层协议。

于 2010-03-05T22:03:42.117 回答
2

如果您觉得特别大胆,可以考虑使用SCTP套接字而不是 TCP 套接字。

于 2010-03-08T04:08:49.603 回答