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

Avi*_*hek 21 sockets buffer tcp blocking

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

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

Bri*_*ite 33

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

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

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

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

一旦本地缓冲区中有空间,send()将复制来自您的呼叫的更多数据.复制完所有数据后,您的通话将会返回.

您将不会收到"连接重置"错误(来自操作系统 - 库可能会执行任何操作),除非连接实际上已重置.

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


Dav*_*rra 6

输出(发送)缓冲区被填满,直到它变满并send()阻塞,直到缓冲区获得足够的空闲以使数据包入队.

如发送手册页所示:

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

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

  • 操作系统仅在确认已发送数据包时才从发送缓冲区中删除数据包.如果接收方从未通信,则数据包被正确发送(在收到PUSH DATA后回复ACK),发送方缓冲区永远不会被释放. (2认同)