在我的系统上输入man recv()
,我得到:
ssize_t
recv(int socket, void *buffer, size_t length, int flags);
…
RETURN VALUES
These calls return the number of bytes received, or -1 if an error occurred.
请注意,length
是无符号类型size_t
,函数的结果是签名ssize_t
。
如果为SSIZE_MAX
传递的值大于length
,那么recv()
填充buffer
指向的内存并返回除了-1
以外的负值的理论情况如何? MSG_WAITALL
?是否有类型的套接字允许很长的消息(Unix域?)?那么{{1}}呢?
答案 0 :(得分:6)
以下是关于ssize_t(从B.2.12 Data Types中提取)的Posix 2008基本原理所说的内容:
ssize_t
这是一个size_t的签名模拟。措辞是这样的,实现可以选择使用更长的类型,或者只是使用size_t基础类型的签名版本。返回ssize_t(read()和write())的所有函数都描述为“实现定义”输入超过{SSIZE_MAX}的结果。
实际上,这并不完全正确,因为返回ssize_t
的套接字函数(包括recv
)没有提及任何超过SSIZE_MAX
的输入。因此,我将其作为意图陈述,暗示recv
中缺少的措辞是错误,可能会在某一天得到纠正。
简而言之,如果您想编写可移植代码,则需要确保I / O段不超过SSIZE_MAX
。此外,SSIZE_MAX
可能小到32767.因此,可移植代码不应该假设它可能更大。
然而,并非每个人都非常关心可移植性。您可能对您的代码运行的实现有所了解。 Posix继续说道:
可以认识到,某些实现可能具有小于size_t的整数。符合要求的应用程序将被限制为不以大于{SSIZE_MAX}的大小执行I / O,但是如果实现提供了扩展范围,则使用扩展的符合要求的应用程序将能够使用整个范围,同时仍然具有单一类型兼容接口
Posix确保recv
返回的唯一值是-1,0或接收的字节数。根据上述措辞,符合要求的实现可以将大于SSIZE_MAX
但小于或等于2*SSIZE_MAX
的值映射到除-1
之外的负整数上。 (如何实现这一目标留给感兴趣的读者:))。据我所知,Linux并没有记录任何此类扩展。