假设我将数据写得非常快[我有内存中的所有数据]到阻塞套接字。进一步假设另一方将非常缓慢地读取数据[例如每次读取之间睡眠 1 秒]。
在这种情况下,写作方面的预期行为是什么?写入操作会阻塞直到对方读取足够的数据,还是写入会返回连接重置之类的错误?
对于阻塞套接字,send()
调用将阻塞,直到所有数据都被复制到该连接的网络堆栈缓冲区中。它不必由另一方接收。此缓冲区的大小取决于实现。
当远程端确认数据时,数据会从缓冲区中清除。这是操作系统的事情,不依赖于实际读取数据的远程应用程序。此缓冲区的大小也取决于实现。
当远程缓冲区已满时,它会告诉您的本地堆栈停止发送。当数据从远程缓冲区中清除(通过远程应用程序读取)时,远程系统将通知本地系统发送更多数据。
在这两种情况下,小型系统(如嵌入式系统)可能具有几 KB 或更小的缓冲区,而现代服务器可能具有几 MB 或更大的缓冲区。
一旦本地缓冲区中有可用空间,send()
将复制来自您的调用的更多数据。复制所有数据后,您的呼叫将返回。
除非连接确实被重置,否则您不会收到“连接重置”错误(来自操作系统 - 库可能会做任何事情)。
所以......在您发送的数据与本地和远程缓冲区大小的总和一样多之前,远程应用程序读取数据的速度并不重要。之后,您将只能send()
像远程一样快recv()
。
输出(发送)缓冲区被填满,直到它被填满并send()
阻塞,直到缓冲区被释放到足以让数据包入队。
正如发送手册页所说:
当消息不适合套接字的发送缓冲区时,send() 通常会阻塞,除非套接字已被置于非阻塞 I/O 模式。
看看这个: http: //manpages.ubuntu.com/manpages/lucid/man2/send.2.html