【问题标题】:can one call of recv() receive data from 2 consecutive send() calls?一次调用 recv() 可以从 2 个连续的 send() 调用中接收数据吗?
【发布时间】:2011-08-30 16:44:28
【问题描述】:

我有一个客户端,它通过 2 个连续的发送调用将数据发送到服务器:

send(_sockfd,msg,150,0);
send(_sockfd,msg,150,0);

当发送第一个发送调用时,服务器正在接收(假设我正在使用 select):

recv(_sockfd,buf,700,0);

请注意,我收到的缓冲区要大得多。

我的问题是:buf 是否有可能同时包含两个味精?我需要 2 个 recv() 调用来获取两个消息吗?

谢谢!

【问题讨论】:

    标签: c


    【解决方案1】:

    TCP 是一个面向流的协议。不是面向消息/记录/块的。也就是说,所有可以保证的是,如果您发送流,字节将按照您发送它们的顺序到达另一端。 RFC 793 或任何其他文档没有规定所涉及的段/数据包的数量。

    这与UDP 形成鲜明对比。正如@R.. 正确所说,在UDP 中,一个完整的消息是在一个操作中发送的(注意术语的变化:message)。尝试使用 TCP 发送一条巨大的消息(比 MTU 大几倍)?没关系,它会给你分的。

    在本地网络或本地主机上运行时,您肯定会注意到(通常)one send == one recv。不要假设。有一些因素会极大地改变它。其中

    • 纳格尔
    • 基础 MTU
    • 内存使用(可能)
    • 定时器
    • 许多其他人

    当然,sendrecv 之间没有对应关系是一件麻烦事,您不能依赖 UDP。这就是SCTP 的原因之一。 SCTP 是一个非常有趣的协议,它面向消息

    返回TCP,这是一个常见的麻烦事。一个同样常见的解决方案是:

    • 确定所有数据包都以固定长度序列(例如 32 个字节)开头
    • 这 32 个字节包含(可能除其他外)随后的消息的大小
    • 当您从套接字读取任意数量的数据时,将数据添加到特定于该连接的缓冲区中。当达到 32 个字节时,读取您仍然需要读取的长度,直到您收到消息。

    真正重要的是要注意线路上实际上没有消息,只有字节。一旦您理解了它,您将在编写网络应用程序方面取得巨大飞跃。

    【讨论】:

      【解决方案2】:

      答案取决于套接字类型,但总的来说,是的,这是可能的。对于 TCP,这是常态。对于 UDP,我相信它不会发生,但我不是网络协议/编程方面的专家。

      【讨论】:

        【解决方案3】:

        是的,它可以而且经常这样做。使用 TCP/IP 时,无法匹配发送和接收调用。您的程序逻辑应该在一个循环中测试 send 和 recv 调用的返回值,该循环在所有内容都发送或接收后终止。

        【讨论】:

          猜你喜欢
          • 2014-08-23
          • 1970-01-01
          • 1970-01-01
          • 2011-04-19
          • 2022-01-01
          • 2020-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多