【问题标题】:Socket Protocol Fundamentals套接字协议基础
【发布时间】:2011-01-23 00:56:06
【问题描述】:

最近,在阅读Socket Programming HOWTO 时,以下部分突然出现在我身上:

但如果您打算重复使用您的套接字进行进一步的传输,您需要意识到套接字上没有“EOT”(传输结束)。我再说一遍:如果一个套接字 send 或 recv 在处理 0 个字节后返回,则连接已断开。如果连接没有断开,您可能会永远等待 recv,因为套接字不会告诉您没有更多要读取的内容(目前)。现在,如果您稍微考虑一下,您就会意识到套接字的一个基本事实:消息必须是固定长度(糟糕),或者是定界(耸耸肩) ),或指示它们的持续时间(更好),或通过关闭连接结束。选择完全由您自己决定,(但有些方法比其他方法更正确)。

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

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

【问题讨论】:

标签: sockets network-protocols


【解决方案1】:

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

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

【讨论】:

  • +1,使用 UDP 固定长度是要走的路。如果你不能把所有东西都放在一个包里,你可能无法把它们放回去。
  • 为什么这很重要,如果 UDP 数据包在途中被丢弃,IP 层不会将 UDP 数据包转发到您的应用程序 - 丢失部分与丢失所有部分相同,对吧?恐怕我已经很久没有写网络应用程序了。
  • “由于 TCP 套接字是可靠的,你可以确保你得到了所有你塞进去的东西”是一个可怕的误解。您可以确定您以正确的顺序接收所有内容,并且数据流以您实际打算作为开始的方式开始,但是如果不使用应用程序级协议结构,您永远无法确定它是否在预期结束的地方结束确定。
  • @Mart:抱歉,我不确定你的意思。如果你将“abcde”写入一个 TCP 套接字,你最终会在接收端得到它。
  • 不,没有这样的保证。您可能会丢失来自 TCP 连接的数据流的结尾(“end”可能很容易从发送到套接字的第一个字节开始)。尝试在具有高 RTT 和丢包率的邋遢网络中使用 TCP,您会发现 TCP 不可靠的令人惊讶的事情。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 一个不错的选择。当程序员不使用无效消息进行测试时,实现可能容易受到缓冲区溢出的影响。
    【解决方案4】:

    如果您正在设计自己的协议,请先查看其他人的工作;那里可能已经有类似的东西,您可以“按原样”使用或重新调整用途和调整。例如; ISO-8583 用于金融交易,HTTPPOP3 都以不同的方式做事,但以被证明有效的方式......事实上,无论如何,看看这些东西是值得的,因为你会学到很多关于现实世界协议的知识放在一起。

    如果您需要编写自己的协议,恕我直言,请尽可能使用长度前缀消息。它们很容易为接收者解析,但如果在开始发送数据之前确定数据的长度成本很高,则可能更难生成。

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 类似于“EOL 分隔的字符串只要它们本身不包含 EOL 字符就很好”,使用零字节来分隔 ASCII 编码的消息会是一个坏主意吗?
      猜你喜欢
      • 2011-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-07
      • 2013-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多