【发布时间】:2012-09-21 08:17:09
【问题描述】:
send() 应返回发送的字节数或错误代码,但我发现的所有示例仅使用错误代码检查它,而不是发送的字节数。
//typical example
int cnt=send(s,query,strlen(query),0);
if (cnt < 0) return(NULL);
//Hey, what about cnt < strlen(query)?
【问题讨论】:
send() 应返回发送的字节数或错误代码,但我发现的所有示例仅使用错误代码检查它,而不是发送的字节数。
//typical example
int cnt=send(s,query,strlen(query),0);
if (cnt < 0) return(NULL);
//Hey, what about cnt < strlen(query)?
【问题讨论】:
问:“send()”是否总是返回整个缓冲区?
答:不,不一定。
来自 Beej 的指南: * http://beej.us/guide/bgnet/html/multi/syscalls.html#sendrecv
send() 返回实际发送的字节数——这可能是 少于您告诉它发送的数量!看,有时你会告诉它 发送一大堆数据,但它无法处理。会火 尽可能多地关闭数据,并相信你会发送其余的 之后。请记住,如果 send() 返回的值与 len 中的值,由您决定发送字符串的其余部分。好的 新闻是这样的:如果数据包很小(小于 1K 左右),它将 可能设法一次性发送整件事。同样,-1 是 出错时返回,并将 errno 设置为错误号。
问:“recv()”是否总是读取整个缓冲区?
A:不,绝对不是。您应该永远假设您收到的缓冲区是“整个消息”。或者假设您收到的消息来自一个,单个消息。
这里有一个很好的简短解释。它适用于 Microsoft/C#,但适用于 所有 套接字 I/O,任何语言:
【讨论】:
不,它没有。
当消息不适合套接字的发送缓冲区时,send() 通常阻塞,除非套接字已被置于非阻塞 I/O 模式。 在非阻塞模式下,它将失败并出现错误 EAGAIN 或 EWOULDBLOCK 案子。 select(2) 调用可用于确定何时可以发送 更多数据。
【讨论】:
答案在man 2 send的另一部分:
When the message does not fit into the send buffer of the socket,
send() normally blocks, unless the socket has been placed in nonblock‐
ing I/O mode. In nonblocking mode it would fail with the error EAGAIN
or EWOULDBLOCK in this case. The select(2) call may be used to deter‐
mine when it is possible to send more data.
或者,或者,POSIX 版本 (man 3p send):
If space is not available at the sending socket to hold the message to
be transmitted, and the socket file descriptor does not have O_NONBLOCK
set, send() shall block until space is available. If space is not
available at the sending socket to hold the message to be transmitted,
and the socket file descriptor does have O_NONBLOCK set, send() shall
fail. The select() and poll() functions can be used to determine when
it is possible to send more data.
因此,虽然部分数据的 read 很常见,但阻塞模式下的部分 send 不应该发生(除非实现细节)。
【讨论】: