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