27

假设我将数据写得非常快[我有内存中的所有数据]到阻塞套接字。进一步假设另一方将非常缓慢地读取数据[例如每次读取之间睡眠 1 秒]。

在这种情况下,写作方面的预期行为是什么?写入操作会阻塞直到对方读取足够的数据,还是写入会返回连接重置之类的错误?

4

2 回答 2

37

对于阻塞套接字,send()调用将阻塞,直到所有数据都被复制到该连接的网络堆栈缓冲区中。它不必由另一方接收。此缓冲区的大小取决于实现。

当远程端确认数据时,数据会从缓冲区中清除。这是操作系统的事情,不依赖于实际读取数据的远程应用程序。此缓冲区的大小也取决于实现。

当远程缓冲区已满时,它会告诉您的本地堆栈停止发送。当数据从远程缓冲区中清除(通过远程应用程序读取)时,远程系统将通知本地系统发送更多数据。

在这两种情况下,小型系统(如嵌入式系统)可能具有几 KB 或更小的缓冲区,而现代服务器可能具有几 MB 或更大的缓冲区。

一旦本地缓冲区中有可用空间,send()将复制来自您的调用的更多数据。复制所有数据后,您的呼叫将返回。

除非连接确实被重置,否则您不会收到“连接重置”错误(来自操作系统 - 库可能会做任何事情)。

所以......在您发送的数据与本地和远程缓冲区大小的总和一样多之前,远程应用程序读取数据的速度并不重要。之后,您将只能send()像远程一样快recv()

于 2013-01-09T18:57:42.237 回答
7

输出(发送)缓冲区被填满,直到它被填满并send()阻塞,直到缓冲区被释放到足以让数据包入队。

正如发送手册页所说:

当消息不适合套接字的发送缓冲区时,send() 通常会阻塞,除非套接字已被置于非阻塞 I/O 模式。

看看这个: http: //manpages.ubuntu.com/manpages/lucid/man2/send.2.html

于 2013-01-09T16:07:05.610 回答