12

send()应返回发送的字节数或错误代码,但我发现的所有示例仅使用错误代码检查它,而不是发送的字节数。

//typical example
int cnt=send(s,query,strlen(query),0);
if (cnt < 0) return(NULL);
//Hey, what about cnt < strlen(query)?
4

3 回答 3

13

问:“send()”是否总是返回整个缓冲区?

答:不,不一定。

来自 Beej 的指南:* http://beej.us/guide/bgnet/html/multi/syscalls.html#sendrecv

send() 返回实际发送的字节数——这可能小于你告诉它发送的字节数!看,有时你告诉它发送一大堆数据,它就是无法处理。它会尽可能多地发送数据,并相信您稍后会发送其余的数据。请记住,如果 send() 返回的值与 len 中的值不匹配,则由您决定发送字符串的其余部分。好消息是:如果数据包很小(小于 1K 左右),它可能会设法一次性发送整个数据包。同样,错误时返回 -1,并将 errno 设置为错误号。

问:“recv()”是否总是读取整个缓冲区?

答:不,绝对不是。你永远不应该假设你收到的缓冲区是“整个消息”。或者假设您收到的消息来自一个单一的消息。

这是一个很好的简短解释。它适用于 Microsoft/C#,但适用于任何语言的所有套接字 I/O :

于 2012-09-29T22:29:56.620 回答
4

答案在另一部分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但不应该发生部分处于阻塞模式的情况(除非实现细节)。

于 2012-09-29T22:32:22.350 回答
3

不,它没有。

有关参考,请参阅send 的手册页

当消息不适合套接字的发送缓冲区时,send() 通常会阻塞,除非套接字已被置于非阻塞 I/O 模式。在非阻塞模式下,它会因错误 EAGAIN 或 EWOULDBLOCK 而失败。select(2) 调用可用于确定何时可以发送更多数据。

于 2012-09-29T22:30:06.520 回答