一次recv()调用可以从2个连续的send()调用中接收数据吗?

时间:2011-05-22 18:23:17

标签: c

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

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

并且当发送第一个发送呼叫时服务器正在接收(假设我正在使用select):

recv(_sockfd,buf,700,0);

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

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

谢谢你!

3 个答案:

答案 0 :(得分:4)

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

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

在本地网络或localhost上运行时,您肯定会注意到(通常)one send == one recv。不要以为这个。有些因素会大大改变它。其中

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

当然,没有sendrecv之间的对应关系是令人讨厌的,你不能依赖UDP。这是SCTP的原因之一。 SCTP是一个非常有趣的协议,它是面向消息的

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

  • 确定所有数据包都以固定长度序列(比如32个字节)开始
  • 这32个字节包含(可能包括其他内容)消息的大小
  • 从套接字读取任意数量的数据时,将数据添加到特定于该连接的缓冲区。当达到32 字节时,请阅读您需要阅读的长度,直至收到消息。

注意线路上确实没有消息,只有字节,这一点非常重要。一旦你理解了它,你就会在编写网络应用程序方面取得巨大的飞跃。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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