Sockets 套接字协议基础

Sockets 套接字协议基础,sockets,network-protocols,Sockets,Network Protocols,最近,在阅读一篇文章时,我突然想到了以下部分: 但是,如果您计划重用套接字进行进一步传输,则需要意识到套接字上没有“EOT”(传输结束)。我重复:如果套接字send或recv在处理0字节后返回,则连接已断开。如果连接没有断开,您可以永远等待recv,因为套接字不会告诉您没有更多内容可读(目前)。现在,如果您仔细考虑一下,您将认识到套接字的一个基本事实:消息必须是固定长度的(恶心),或者是分隔的(耸耸肩),或者指示它们的长度(好得多),或者通过关闭连接来结束。这完全是你的选择,(但有些方法比其他方

最近,在阅读一篇文章时,我突然想到了以下部分:

但是,如果您计划重用套接字进行进一步传输,则需要意识到套接字上没有“EOT”(传输结束)。我重复:如果套接字send或recv在处理0字节后返回,则连接已断开。如果连接没有断开,您可以永远等待recv,因为套接字不会告诉您没有更多内容可读(目前)。现在,如果您仔细考虑一下,您将认识到套接字的一个基本事实:消息必须是固定长度的(恶心),或者是分隔的(耸耸肩),或者指示它们的长度(好得多),或者通过关闭连接来结束。这完全是你的选择,(但有些方法比其他方法更正确)

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


一般来说,是否最好在每条消息中包含消息大小(可能是在一个标题中),正如本文或多或少所断言的那样?是否有其他方法更可取的情况?

常见协议要么在头中指定长度,要么是分隔的(例如HTTP)


请记住,这还取决于您是使用TCP还是UDP套接字。因为TCP套接字是可靠的,所以您可以确保您得到了插入它们的所有内容。UDP的情况不同,而且更复杂。

这些确实是我们对TCP的选择。例如,HTTP混合使用第二个、第三个和第四个选项(两个新行结束请求/响应头,其中可能包含
内容长度
头或表示分块编码,或者它可能会说
连接:关闭
,不给您内容长度,但希望您依赖于读取EOF。)


我更喜欢第三个选项,即自描述消息,但如果合适的话,固定长度很容易。

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

如果你在设计自己的协议,那么先看看别人的工作;可能已经有类似的东西,你可以使用“原样”或者重新调整用途和调整。例如对于金融TXN,或者所有的做法都不同,但都被证明是有效的。。。事实上,无论如何,看看这些东西都是值得的,因为你将学到很多关于真实世界协议是如何组合在一起的


如果您需要编写自己的协议,IMHO会尽可能选择长度前缀消息。对于接收者来说,解析它们既简单又高效,但是如果在开始发送数据之前确定数据的长度成本很高,那么生成它们可能会更困难

决策应取决于您想要发送的数据(数据是什么,如何收集)。如果数据是固定长度的,那么固定长度的数据包可能是最好的。如果数据可以很容易地(无需转义)分割成分隔的实体,那么分隔可能是好的。如果在开始发送数据块时知道数据大小,那么len前缀可能更好。如果发送的数据始终是单个字符,甚至是单个位(例如“开”/“关”),则与固定大小的一个字符消息不同的任何内容都会太多


还要考虑协议可能如何演变。只要EOL分隔字符串本身不包含EOL字符,就可以使用EOL分隔字符串。固定长度可能会很好,直到数据可以通过一些可选部分进行扩展,等等。

+1使用UDP固定长度是一个不错的选择。如果你不能将所有数据包都放在一个数据包中,你可能无法将其放回一起。为什么这很重要,如果UDP数据包在传输过程中被屏蔽,IP层不会将其转发到你的应用程序-丢失部分就等于丢失了所有数据包,对吗?恐怕我已经很久没有写过网络应用程序了,“既然TCP套接字是可靠的,你就可以确保你得到了你塞进它们的所有东西”,这是一个可怕的误解。您可以确保接收到的所有内容都按正确的顺序进行,并且数据流以您实际打算作为开始的内容开始,但如果不使用应用程序级协议结构来确定,您永远无法确定数据流是否在计划结束的位置结束。@Mart:抱歉,我不确定您的意思。如果你将“abcde”写入TCP套接字,你最终会在接收端得到它。不,没有这样的保证。您可能会从TCP连接中丢失数据流的结尾(“end”可能很容易从发送到套接字的第一个字节开始)。尝试在具有高RTT和packetloss的松散网络中使用TCP,您会发现TCP的不可靠性令人惊讶。这是一个不错的选择。当程序员不使用无效消息进行测试时,该实现可能容易受到缓冲区溢出的影响。上面的链接已断开。这是关于python套接字编程的,新链接类似于“EOL分隔字符串,只要它们本身不包含EOL字符就好”,使用零字节分隔ASCII编码的消息是个坏主意吗?