问题 套接字协议基础


最近,在读书的时候 套接字编程HOWTO 以下部分跳了出来:

但是,如果您计划重新使用套接字进行进一步传输,则需要意识到套接字上没有“EOT”(传输结束)。我再说一遍:如果在处理0字节后套接字send或recv返回,则连接已断开。如果连接没有被破坏,你可以永远等待一个recv,因为套接字不会告诉你没有什么可读的(现在)。现在,如果你仔细考虑一下,你就会发现套接字的一个基本事实:消息必须是 固定长度 (哎呀),或者是 分隔 (耸肩),或 表明他们有多长 (好多了),或者 通过关闭连接来结束。选择完全属于你,(但有些方式比其他方式更严格)。

本节重点介绍了如何编写套接字“协议”以传递消息的4种可能性。我的问题是,用于实际应用程序的首选方法是什么?

通常最好在每条消息中包含消息大小(可能在标题中),因为文章或多或少断言?有没有其他方法更可取的情况?


12635
2018-03-03 03:36


起源

上面的链接被破坏了。 - cdosborn
这是关于python套接字编程,新的链接是 docs.python.org/2/howto/sockets.html - HUA Di


答案:


公共协议要么在标头中指定长度,要么分隔(例如HTTP)。

请记住,这还取决于您是使用TCP还是UDP套接字。由于TCP套接字是可靠的,因此您可以确保将所有内容都塞进其中。使用UDP,故事是不同的,也是更复杂的。


5
2018-03-03 03:49



+1,UDP固定长度是要走的路。如果您不能将所有内容都放入一个数据包中,则可能无法将其重新组合在一起。 - Carl Norum
为什么重要的是,如果UDP路由器沿途被传输,IP层将不会将UDP数据包转发到您的应用程序 - 缺少部分与丢失所有部分相同,对吧?自从我写一个网络应用程序以来已经很长时间了,我很害怕。 - Carl Norum
“既然TCP套接字是可靠的,你可以确定你把所有东西都塞进去了”是一个可怕的错误观念。您可以确定以正确的顺序接收所有内容,并且数据流以您实际打算作为开始的内容开始,但是您永远无法确定它是否在不使用应用程序级协议结构的情况下结束确定。 - Mart Oruaas
@Mart:抱歉,但我不确定你的意思。如果你将“abcde”写入TCP套接字,你最终会在接收端得到它。 - Eli Bendersky
不,没有这样的保证。您可能会丢失来自TCP连接的数据流的结束(“结束”可能很容易从发送到套接字的第一个字节开始)。尝试在具有高RTT和数据包丢失的草率网络中使用TCP,您将发现有关TCP不可靠性的令人惊讶的事情。 - Mart Oruaas


这些确实是我们对TCP的选择。例如,HTTP使用第二,第三和第四选项的混合(双新行结束请求/响应头,其中 威力 包含 Content-Length 标题或指示 分块编码或者它可能会说 Connection: close 并没有给你内容长度,但希望你依靠阅读EOF。)

我更喜欢第三种选择,即自我描述的消息,虽然固定长度在适当时很容易。


2
2018-03-03 03:51





如果您正在设计自己的协议,那么先看看其他人的工作;可能已经存在类似的东西你可以“按原样”使用或重新调整和调整。例如; ISO-8583 对于金融txns, HTTP 要么 POP3 所有事情都以不同的方式做事,但事实证明是有效的......事实上,无论如何你都应该看看这些事情,因为你将学到很多关于如何将现实世界的协议放在一起的知识。

如果您需要编写自己的协议,那么恕我直言,在可能的情况下更喜欢长度带前缀的消息。它们可以轻松高效地解析接收器,但如果在开始发送数据之前确定数据长度成本很高,则可能难以生成。


2
2018-03-03 06:56





我不知道是否有首选方案。在我们的实际情况(客户端 - 服务器应用程序)中,我们使用将总消息长度作为第一个数据之一发送的选项。它很简单,适用于我们的TCP和UDP实现。在两种情况下读取数据时,它使逻辑合理地“简单”。使用TCP,代码量相当小(相比之下)。 UDP版本有点(低估)更复杂但仍然依赖于初始数据包中传递的大小来知道何时发送了所有数据。


1
2018-03-03 04:11



一个不错的选择。当程序员不使用无效消息进行测试时,实现可能容易受到缓冲区溢出的影响。 - Zan Lynx


决定应取决于您要发送的数据(它是什么,如何收集)。如果数据是固定长度的,那么固定长度的数据包可能是最好的。如果数据可以很容易(不需要转义)拆分为分隔实体,那么分隔可能是好的。如果您在开始发送数据时知道数据大小,那么len-prefixing可能会更好。如果发送的数据总是单个字符,或者甚至是单个字符(例如“开”/“关”),则任何不同于固定大小的一个字符消息的内容都将过多。

还要考虑协议如何发展。 EOL分隔的字符串很好,只要它们本身不包含EOL字符。固定长度可能是好的,直到数据可以扩展一些可选部分等。


1
2018-03-03 18:29