Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
长度为零的recv()是否有效?_C_Sockets - Fatal编程技术网

长度为零的recv()是否有效?

长度为零的recv()是否有效?,c,sockets,C,Sockets,使用C中的recv()函数从“stream”套接字读取,len参数是否可以为零 recv()函数为“remote connection closed”(远程连接已关闭)返回零,并返回正常操作中实际读取的字节数,因此如果读取零字节,则听起来有问题 附加说明 是的,我知道要单独处理它,但我不知道这个函数是否可以处理它,我找不到任何关于它的文档。我认为长度参数不能为零,因为即使是空字符串(消息)也需要以“\0”结尾。我很确定它没有定义。。。看看Linux,它一直传递到“驱动程序”(如tcp等),所以它

使用C中的recv()函数从“stream”套接字读取,len参数是否可以为零

recv()函数为“remote connection closed”(远程连接已关闭)返回零,并返回正常操作中实际读取的字节数,因此如果读取零字节,则听起来有问题

附加说明

是的,我知道要单独处理它,但我不知道这个函数是否可以处理它,我找不到任何关于它的文档。

我认为长度参数不能为零,因为即使是空字符串(消息)也需要以“\0”结尾。

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

我认为你最好不要这样做,根据你想做的事情使用带有1字节的MSG_PEEK或poll()。

我相信答案是“视情况而定”如果标准中没有指定它(事实上我相信不是),任何实现都可以随心所欲

  • 如果出现
    EINVAL
  • 它可以挂起来
  • 它可以返回
    0
    并继续
  • 它可以打印一条有趣的消息,并启动游戏rogue(我理解,
    gcc
    用于这样做:))

实际上在我的实现中,它返回0并继续。要检查它是否失败或只是返回了0,您可以在调用后检查
errno
,这样就不会像您想象的那样有问题了。

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

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

如果消息太长,无法放入提供的缓冲区,则可能会丢弃多余的字节,具体取决于从中接收消息的套接字类型。 根据文档,我希望我的
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函数只是系统调用的瘦接口。请随意用C重写它们。)

POSIX关于
recv()
的页面并不清楚。在非规范性部分(“应用程序用法”)中,如果未给出任何标志,则表示套接字上的
recv()
等同于
read()
。POSIX关于
read();如果没有错误或实现没有检查,则不会发生任何事情,并返回0。

不确定这有什么问题吗?当您要求read()读取0字节时,您希望它返回什么?1? -1?@BlackBear,还没有,如果有人知道,我更愿意得到答案,而不是构造一个测试-处理套接字,即使是最简单的测试也需要设置要连接的东西,建立连接,然后尝试看看会发生什么。我刚刚在Windows上在阻塞套接字TCP上进行了尝试
recv(s,b,0,0)
挂起,直到有一些传入数据或连接关闭,然后返回0。如果已经有传入数据,它会立即返回0
WSAGetLastError()
errno
在此之后返回0。来自套接字的“消息”不一定是以nul结尾的字符串。。。。它也不一定是一根弦:-好的,我的坏。注意。尽管C语言允许使用零字节缓冲区,但我仍然认为这一概念值得商榷。我的系统(Linux)上的文档清楚地定义了
recv
的行为,而缓冲区长度为零并不能阻止任何这种行为。我不明白为什么你认为零在某种程度上是异常的,并且在某种程度上是异常的,以至于定义的行为应该被忽略,所以我认为你的答案是错误的。请参阅我的答案以了解详细信息。正如我所说的,我觉得这可能是一个问题,因为返回值很奇怪。我不知道也不确定这就是我问的原因。返回零通常意味着插座已关闭。因此,当给定的长度为零时,recv()无法返回任何有意义的内容,除了EINVAL。所以,永远不要调用length=0的recv()。虽然这是可行的,但perl的行为方式可能是这样的,而C的实现不会这样吗?可能是这个“薄接口”也用一些边缘案例处理来包装它。我很感激你的回答,但我仍然觉得“视情况而定”是更准确的答案。当(如果有的话)我最终将自己测试它时,我可能会在这里更新。@Xenorose,我使用的是系统文档(
man recv
),而不是Perl。如果你发邮件给我,我们非常欢迎你用C语言重新实现测试(ikegami@adaelis.com),我甚至会用它替换我答案中的Perl代码。
$ 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