当我将数据写入阻塞套接字时会发生什么,比另一边读取更快?

时间:2013-01-09 16:01:00

标签: sockets tcp buffer blocking

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

在这种情况下写作方面的预期行为是什么? 写操作块是否会在另一侧读取足够的数据,否则写操作会返回错误,如连接重置?

2 个答案:

答案 0 :(得分:29)

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

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

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

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

一旦本地缓冲区中有空间,您的send()调用中将会复制更多数据。复制完所有数据后,您的电话将会返回。

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

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

答案 1 :(得分:6)

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

如发送手册页所示:

当消息不适合套接字的发送缓冲区时,        send()通常是块,除非套接字已放入非        阻止I / O模式。

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