使用C中的recv()函数从'流'套接字读取len参数可以为零吗?长度为零的recv()是否有效?
recv()函数对于'远程连接关闭'返回零和正常操作中实际读取的字节数,所以如果它应该读取零字节听起来有问题。
P.S.
是的,我知道单独处理它,并没有得到这种情况,我仍然想知道该功能是否可以处理它,我找不到任何有关它的文档。
使用C中的recv()函数从'流'套接字读取len参数可以为零吗?长度为零的recv()是否有效?
recv()函数对于'远程连接关闭'返回零和正常操作中实际读取的字节数,所以如果它应该读取零字节听起来有问题。
P.S.
是的,我知道单独处理它,并没有得到这种情况,我仍然想知道该功能是否可以处理它,我找不到任何有关它的文档。
我相信答案是“取决于”。 如果它没有被标准(并且实际上我相信它不是)规定的,任何实现都可以按照它的意愿进行。
EINVAL
0
,继续gcc
: )))其实在我的实现中,它返回0并继续。要检查它是否失败或只是返回0,您可以在电话后检查errno
,因此它不像您想象的那样有问题。
我不认为长度参数可以是零,因为即使是一个空字符串(消息)需要终止'\ 0'。
来自套接字的“消息”不一定是以nul结尾的字符串。 – 2011-05-13 16:29:14
...并不一定是一个字符串:-D – 2011-05-13 16:31:05
好吧,我的坏。注意到了。尽管C语言允许,但我仍然认为零字节缓冲区的概念值得商榷。 – 2011-05-13 18:10:38
我很确定它是未定义的......看着Linux它一直传递到“驱动程序”(即.tcp等),所以它可能意味着什么,但我不认为这是意义被很好地定义。当然,SuS并没有对此做任何明确的说明。
我认为你几乎可以肯定不会这样做,并且根据你想要做的事情使用带有1字节或poll()的MSG_PEEK。
为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.)
POSIX的页面约recv()
是不是很清楚它。在非标准部分(“应用程序使用”)中,如果没有给出标志,则说明在套接字上的recv()
相当于read()
。 POSIX的页面read()
表示读取0字节可能会检查错误;如果没有错误或执行不检查,则不会发生任何事情并返回0。
你试过了吗? – BlackBear 2011-05-13 16:21:40
不确定为什么这是有问题的?当你要求它读取0字节时,你期望read()返回什么? 1? -1? – stijn 2011-05-13 16:26:27
@BlackBear,还不如,如果有人知道构建一个测试,我宁愿得到答案 - 即使最简单的测试需要设置某些东西来连接,建立连接,然后尝试看看会发生什么。 – Eran 2011-05-13 16:33:56