最近,在读书的时候 套接字编程HOWTO 以下部分跳了出来:
但是,如果您计划重新使用套接字进行进一步传输,则需要意识到套接字上没有“EOT”(传输结束)。我再说一遍:如果在处理0字节后套接字send或recv返回,则连接已断开。如果连接没有被破坏,你可以永远等待一个recv,因为套接字不会告诉你没有什么可读的(现在)。现在,如果你仔细考虑一下,你就会发现套接字的一个基本事实:消息必须是 固定长度 (哎呀),或者是 分隔 (耸肩),或 表明他们有多长 (好多了),或者 通过关闭连接来结束。选择完全属于你,(但有些方式比其他方式更严格)。
本节重点介绍了如何编写套接字“协议”以传递消息的4种可能性。我的问题是,用于实际应用程序的首选方法是什么?
通常最好在每条消息中包含消息大小(可能在标题中),因为文章或多或少断言?有没有其他方法更可取的情况?
公共协议要么在标头中指定长度,要么分隔(例如HTTP)。
请记住,这还取决于您是使用TCP还是UDP套接字。由于TCP套接字是可靠的,因此您可以确保将所有内容都塞进其中。使用UDP,故事是不同的,也是更复杂的。
这些确实是我们对TCP的选择。例如,HTTP使用第二,第三和第四选项的混合(双新行结束请求/响应头,其中 威力 包含 Content-Length
标题或指示 分块编码或者它可能会说 Connection: close
并没有给你内容长度,但希望你依靠阅读EOF。)
我更喜欢第三种选择,即自我描述的消息,虽然固定长度在适当时很容易。
如果您正在设计自己的协议,那么先看看其他人的工作;可能已经存在类似的东西你可以“按原样”使用或重新调整和调整。例如; ISO-8583 对于金融txns, HTTP 要么 POP3 所有事情都以不同的方式做事,但事实证明是有效的......事实上,无论如何你都应该看看这些事情,因为你将学到很多关于如何将现实世界的协议放在一起的知识。
如果您需要编写自己的协议,那么恕我直言,在可能的情况下更喜欢长度带前缀的消息。它们可以轻松高效地解析接收器,但如果在开始发送数据之前确定数据长度成本很高,则可能难以生成。
我不知道是否有首选方案。在我们的实际情况(客户端 - 服务器应用程序)中,我们使用将总消息长度作为第一个数据之一发送的选项。它很简单,适用于我们的TCP和UDP实现。在两种情况下读取数据时,它使逻辑合理地“简单”。使用TCP,代码量相当小(相比之下)。 UDP版本有点(低估)更复杂但仍然依赖于初始数据包中传递的大小来知道何时发送了所有数据。
决定应取决于您要发送的数据(它是什么,如何收集)。如果数据是固定长度的,那么固定长度的数据包可能是最好的。如果数据可以很容易(不需要转义)拆分为分隔实体,那么分隔可能是好的。如果您在开始发送数据时知道数据大小,那么len-prefixing可能会更好。如果发送的数据总是单个字符,或者甚至是单个字符(例如“开”/“关”),则任何不同于固定大小的一个字符消息的内容都将过多。
还要考虑协议如何发展。 EOL分隔的字符串很好,只要它们本身不包含EOL字符。固定长度可能是好的,直到数据可以扩展一些可选部分等。