在客户端/服务器应用程序中,不同长度的文本数据将在客户端和服务器之间来回发送,我应该如何标记正在发送的数据包的结尾?例如,当服务器从客户端接收分组数据时,服务器如何知道客户端分组已完全被接收?
告诉服务器在数据之前要接收的数据包的全长或是否有标记数据包末尾的内容更常见?
发送的一些数据只有几个字符长,有些可能是数千个字符。
答案 0 :(得分:30)
TCP提供连续的数据流。使用数据包实现 TCP,但TCP的全部意义是隐藏它们。
把它想象成你想要绘制的墙。墙由砖砌成。用砂浆将砖粘在一起,并施加石膏使墙壁表面变得光滑。砖是IP包,TCP是石膏。
所以现在你有了光滑的TCP隧道,你想在其中添加一些结构。您想要绘制框,以便您的图形彼此分开。这就是你想要做的:在你的数据中添加一些“管理”结构(图纸周围的方框)。
许多协议使用packet
的概念,这是一组以固定格式管理头开头的数据。标头包含足够的信息来决定数据包的结束位置;例如,它包括分组长度。 HTTP使用Content-Length
标头,或(使用HTTP / 1.1)使用“chunked transfer encoding”,其中数据被分成一个或多个迷你数据包,每个迷你数据包都包含一个简单的标头,其中包含一个简单的包长度指示。
另一种方法是使用一个特殊的终止子序列,它不能出现在“普通数据”中。如果您的数据是文本,那么您可以使用零值的字节作为终止符。
另一种方法是使用自终止数据。这是以这样一种方式构建的数据,您可以随时知道是否已到达元素的结尾。例如,XML数据被组织为嵌套的标记对,例如<foo>...</foo>
。到达结束标记(</foo>
)时,您知道该元素已完成。
答案 1 :(得分:3)
以一种开头包含长度字段的方式构建数据包。
答案 2 :(得分:2)
如果发件人知道长度,那么发件人应该提供前面的长度作为固定大小字段,然后是可变大小数据。
尾部标记的优点是接收器可以优化预期的数据量,例如:分配正确大小的缓冲区。例如,TCP / IP协议上的存储与TCP / IP具有相同的问题。在这些情况下,标题提供了随后预期数据的长度。
稍后,您可能会在“标题”中找到其他位。你会很高兴你有一些结构可以发展你自己的第5层协议。
答案 3 :(得分:1)
从HTTP获取提示。
使用终结符字符序列,或在邮件标题中的某处指定长度,或使用两者的巧妙组合。
与HTTP一样:标题以CR-LF-CR-LF结尾。如果标题后面有数据,则数据长度位于其中一个标题中。
答案 4 :(得分:1)
如果您感觉特别大胆,可以考虑使用SCTP套接字而不是TCP套接字。
答案 5 :(得分:1)
如果您在开头编码长度,请注意垃圾。例如,如果您使用4个二进制字节作为长度并且某些外部探测器发送HTTP请求,您可能会得到一个巨大的数字并且永远等待(更不用说分配可能导致程序崩溃的缓冲区)。我通过不同的函数发送两次长度并比较它们(例如~len和len xor 0x139AF321)。如果有人正在尝试使您的程序崩溃,您还应设置最大值。如果我的长度不好,我就关闭连接。
如果您的流量已加密,则超出HMAC。