7

在我的系统上打字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_MAXfor length,那么理论上recv()填充指向的内存buffer并返回除 之外的负值的情况如何-1?是否有类型的套接字允许很长的消息(Unix 域?)?怎么样MSG_WAITALL

4

1 回答 1

6

以下是 Posix 2008 基本原理对 ssize_t 的说明(摘自B.2.12 Data Types):

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 没有记录任何此类扩展。

于 2013-06-20T20:56:36.140 回答