繁体   English   中英

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

[英]recv() with length zero is valid?

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

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

PS
是的我知道单独处理它,并没有达到这种情况,仍然我想知道该功能是否可以处理它,我找不到任何关于它的文档。

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

  • 它可能会因EINVAL而失败
  • 它可能会挂起
  • 它可以返回0并继续
  • 它可以打印一个有趣的消息并启动游戏流氓(我理解gcc用来做那:)))

实际上在我的实现上,它返回0并继续。 要检查它是否失败或只是返回0,您可以在通话后检查errno ,因此它不像您想象的那样有问题。

我系统上的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中重写它们。)

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM