【问题标题】:Usage of read in socket programming套接字编程中read的使用
【发布时间】:2016-12-15 06:12:00
【问题描述】:

在c编程中使用阻塞函数读取时,有什么方法可以区分不同数据包的有效载荷吗?我从 TCP 客户端以数据包的形式发送每条消息,当我在 TCP 服务器中读取(使用读取功能)它时,我将所有消息放在缓冲区中,中间没有任何分隔符。

【问题讨论】:

  • TCP 是面向流的。就您的应用程序而言,没有数据包,只有不间断的字节流。协议底层的数据包可以被任何中间方随意拆分和合并,所以看它们是没有意义的。

标签: c linux sockets


【解决方案1】:

您必须自己在应用层实现。

一种方法是例如类型-长度-值。

您发送的每条消息都具有以下结构:

1 byte | 2 byte | length bytes
type    length   value

更多详情here.

请注意read 不会准确读取指定的字节数,它可以读取的字节数更少 - 因此您需要检查它的返回值。例如见this

还有一些二进制协议的陷阱,你可能想成为aware

另外,建议您阅读一些网络编程的背景知识,例如here - 见第 7 章。

【讨论】:

  • 如果客户端是 PUTTY 或 telnet 之类的,有什么办法吗?
  • @Govindh 你必须把分隔符放在那里,如果适合你,没有人会这样做。
  • T-L-V 是此任务的首选方法。如果您正在使用第三方工具,他们可能有 T-L-V 或可能使用某种分隔符来传达消息的结尾。这是必需的,因为 TCP 是一种没有任何固有消息边界的字节流协议。 Telnet 我猜使用 CR LF 分隔符 (freesoft.org/CIE/RFC/1123/31.htm)
  • TCP 中没有数据包边界的概念。数据包边界由应用层定义。因此,您需要研究应用程序如何定义数据包边界。例如一个简单的服务器可能会将一个数据包定义为 3 个字段的组合,如 Tag-Length-Value 中的,因此您可以首先读取 1 字节标签,然后是长度,然后是实际数据,即长度字节长。
  • putty 只是一个应用程序。你在 putty 中使用什么协议?
【解决方案2】:

TCP是面向流的,这意味着没有可以将它们分开的数据包,因此您必须实现您的协议,例如您可以在发送每个数据包之前发送4字节的标头数据并告诉接收者下一个数据包大小,在接收端,你应该总是读取一个 4 字节的头(标识下一个数据包的大小)并使用头中指定的大小进行阻塞读取。

另一个选择是使用固定大小的数据包,所以每次你必须从 TCP 缓冲区读取固定大小的数据包。

与 TCP 不同,UDP 是面向数据包的,正如您所愿。在 UDP 数据包中以发送的大小接收,不会发生其他缓冲或连接,但它是不可靠的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    • 2010-10-18
    • 2020-12-26
    • 1970-01-01
    相关资源
    最近更新 更多