长度为零的recv()有效吗?

时间:2011-05-13 16:09:22

标签: c sockets

使用C中的recv()函数从'stream'套接字读取,len参数可以为零吗?

recv()函数为'远程连接关闭'返回零,并且在正常操作时实际读取的字节数,因此如果它应该读取零字节,则听起来有问题。

P.S。
是的我知道单独处理它,并没有达到这种情况,我仍然想知道函数是否可以处理它,我找不到任何关于它的文档。

5 个答案:

答案 0 :(得分:4)

我相信答案是“这取决于”。 如果标准未指定(事实上我认为不是),任何实施都可以随心所欲。

  • EINVAL
  • 可能会失败
  • 可以挂起
  • 它可以返回0并继续
  • 它可能会打印出一条有趣的消息并启动游戏流氓(我理解gcc曾经这样做:)))

实际上在我的实现上,它返回0并继续。要检查它是否失败或只是返回0,您可以在通话结束后检查errno,这样就不会出现问题。

答案 1 :(得分:3)

我系统上的recv文档(Linux)说

如果套接字上没有可用消息,则接收呼叫等待消息到达

如果消息太长而无法容纳在提供的缓冲区中,则可能会丢弃多余的字节,具体取决于接收消息的套接字类型。

根据文档,我希望我的recv等待消息,然后有效地丢弃它(UDP)或将其保留在流(TCP)中。

这可用于测试非阻塞TCP套接字是否有数据等待。

更新:测试显示文档的这种解释是准确的。

服务器:

$ perl -MIO::Socket::INET -E'
   my $s = IO::Socket::INET->new(Listen => 1) or die $!;
   say $s->sockport;

   my $c = $s->accept or die $!;
   say "[".localtime."] connected";

   $c->recv(my $buf, 0) // die $!;
   say "[".localtime."] received";

   say <$c>;
'
39493
[Fri May 13 13:49:53 2011] connected
[Fri May 13 13:49:55 2011] received
foo

客户端:

$ perl -MIO::Socket::INET -E'
   my $s = IO::Socket::INET->new(
      PeerAddr => "127.0.0.1",
      PeerPort => $ARGV[0],
   ) or die $!;
   sleep 2;
   say $s "foo";
' 39493

(这些Perl函数只是系统调用的精简接口。可以在C中重写它们。)

答案 2 :(得分:1)

我很确定它是未定义的...看着Linux它一直传递到“驱动程序”(即.tcp等)所以它可能意味着什么,但我再也不认为这意味着定义得很好。当然,SuS没有明确说明这一点。

我认为你几乎肯定更好,只是不这样做,并使用MSG_PEEK 1字节或poll()取决于你想做什么。

答案 3 :(得分:0)

POSIX关于recv()的页面并不是很清楚。在非规范部分(“应用程序使用”)中,如果没有给出标志,则套接字上的recv()等同于read()。 POSIX关于read()的页面表示读取0字节可能会检查错误;如果没有错误或者实现没有检查,则没有任何反应,返回0。

答案 4 :(得分:-3)

我认为长度参数不能为零,因为即使空字符串(消息)需要以'\ 0'终止。