send()总是发送整个缓冲区吗?

Jof*_*sey 10 c sockets linux

send() 应该返回发送的字节数或错误代码,但是我发现的所有示例都只检查错误代码,但不检查发送的字节数.

//typical example
int cnt=send(s,query,strlen(query),0);
if (cnt < 0) return(NULL);
//Hey, what about cnt < strlen(query)?
Run Code Online (Sandbox Code Playgroud)

pau*_*sm4 13

问:"send()"总是返回整个缓冲区吗?

答:不,不一定.

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

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

问:"recv()"是否始终读取整个缓冲区?

答:不,绝对不是.你永远不应该假设你收到的缓冲区是"整个信息".另外,假设您收到的消息是从一个,单一的消息.

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

  • -1:完全向后 - 对于任何基于流的协议(例如TCP),如果本地缓冲区已经从先前的发送中几乎已满,则发送可能返回少于请求的量.对于数据报协议(例如UDP),发送将失败或将整个缓冲区作为数据包发送 - 不可能进行部分发送. (5认同)

Mar*_*nde 5

答案在另一部分man 2 send

\n\n
   When the message does not fit into  the  send  buffer  of  the  socket,\n   send()  normally blocks, unless the socket has been placed in nonblock\xe2\x80\x90\n   ing I/O mode.  In nonblocking mode it would fail with the error  EAGAIN\n   or  EWOULDBLOCK in this case.  The select(2) call may be used to deter\xe2\x80\x90\n   mine when it is possible to send more data.\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,POSIX 版本 ( man 3p send):

\n\n
   If  space is not available at the sending socket to hold the message to\n   be transmitted, and the socket file descriptor does not have O_NONBLOCK\n   set,  send()  shall  block  until  space is available.  If space is not\n   available at the sending socket to hold the message to be  transmitted,\n   and  the  socket file descriptor does have O_NONBLOCK set, send() shall\n   fail. The select() and poll() functions can be used to  determine  when\n   it is possible to send more data.\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,虽然read部分数据很常见,但阻塞模式下的部分数据send不应发生(除非实现细节)。

\n