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