Linux网络编程。"read([...])"背后发生了什么?

4

ssize_t read(int fd, void * data, size_t count); 这个函数到底是干什么的?

网上的许多文章都说它会尝试从文件描述符 fd 中读取数据。那这是什么意思呢?"尝试"是指什么?另外,这个函数是怎样设计的呢?操作系统会缓存传入的消息吗?还是说这是一个实时操作?我是说,如果我不及时"读取",是否有可能导致某些数据包丢失?

编辑:

我一直在想为什么这个函数不是阻塞式的。然后我想知道为什么 read(...) 函数具有比代码片段中看到的所有其他函数更多的参数。最后我意识到它是read(...) 而不是recv(...)。真不幸,它仍然几乎按照我的预期工作。有趣的是,我们的联想能力常常与我们开玩笑(不要修改)。我不得不承认,用德语示例对读者有更大的影响......

2个回答

4

Linux会默认缓存任何到达连接的TCP套接字上的数据,最多几兆字节。您不必在数据到达时立即读取。

netstat -tn将显示每个已连接套接字的Recv-QSend-Q,这是每个方向上排队的字节数。


-1

正如Erik Ekman所回答的那样,即使您不认真阅读数据,系统也会缓冲一些数据。

当缓冲区变得越来越满时,接收方的TCP/IP实现将减小广告接收窗口大小,导致对等方发送较小的数据块,有效地限制传输速度。当缓冲区已满时,窗口大小降为零,对等方将被允许不再发送任何额外的数据。即使发生这种情况,也不会丢失任何数据,因为对等方会在接收缓冲区被清除后恢复发送数据包。

正确的TCP/IP实现保证没有数据仅仅通过跳过而丢失——连接要么是可靠的并且工作正常,要么完全丢失,这由read返回-1来指示。


整个第二段都是不正确的。一旦接收缓冲区填满,接收器会通告零接收窗口,发送方将完全停止发送,直到接收器通告非零窗口。没有减速,没有重发,因此也没有丢失。 - user207421
@EJP 当缓冲区完全填满时,接收窗口才会变为0大小;随着缓冲区变满,接收器将减小它,导致吞吐量减慢。无论如何,如果在缓冲区已满的情况下某些数据包因任何原因到达,则它们将被丢弃。 - user4815162342
当然,较小的接收窗口会导致吞吐量降低,但最终原因是读者比作者慢。读者不会“指示对等方减速”,它会告诉对等方在窗口关闭之前可以发送多少数据。如果某些数据包由于某种原因发送到零接收窗口中,则发送方不应连接到Internet,因为这违反了RFC的规定。 - user207421
@EJP 是的,读取器比写入器慢是首先发生的情况。 "指示对等方减速"是缓冲区即将满时发生的高级描述,以及您了解该机制的详细信息。我会重新措辞答案,使其更加精确。 - user4815162342

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接