读取时的套接字行为

Posted

技术标签:

【中文标题】读取时的套接字行为【英文标题】:socket behavior on read 【发布时间】:2009-11-16 17:43:30 【问题描述】:

客户端每 1 秒向套接字写入 5 个字节。 服务器不断地从套接字中读取。服务器端的缓冲区长度为 10 个字节。所以函数看起来像这样

 read(fd, buf, 10);

服务器每次读取 5 个字节。

现在客户端连续写入 5 个字节。 服务器是一样的。服务器每次读取 10 个字节。

套接字上的读取返回的字节数与缓冲区中可用的字节数一样多。 它不会等待填满缓冲区。

它与 SO_RCVLOWAT 有什么关系。 我读到这个套接字选项只在 select/poll io 中起作用。

谢谢

更新

我将 SO_RCVLOWAT 更改为 10,现在它在接收缓冲区中至少等待 10 个字节。所以看起来它确实与接收缓冲区的低水位标记有关。

但我无法将低水位线设置为 0。在这种情况下,它总是将其设置为 1。为什么会这样?

【问题讨论】:

【参考方案1】:

我认为 10 实际上是缓冲区的长度,因此读取将读取最多 10 个字节,但可能无法将所有内容都放入其中,或者可能无法将其填满。我相信它实际上返回写入缓冲区的字节数。

不,它通常不会等到缓冲区满才返回。

【讨论】:

【参考方案2】:

如果您没有设置非阻塞 I/O,则 read() 调用将等待,直到您请求的所有字节都可用或套接字上出现错误。

如果您确实设置了非阻塞 I/O,则无法保证您甚至会获得 5 个字节 - 您可能会以 2 读取一次,以 6 读取一次 - 这取决于系统和网络时间。

【讨论】:

【参考方案3】:

如果要填充 10 字节的缓冲区,可以将 SO_RCVLOWAT 设置为 10,它应该可以正常工作。

即使没有可用的SO_RCVLOWAT 字节(至少在Linux 上),poll/select 也会发出可读的套接字信号。如果您打算将套接字与 poll/select 一起使用,请注意在 poll/select 之后调用 read/recv/etc... 可能会阻塞,直到 SO_RCVLOWAT 字节数可用。

【讨论】:

以上是关于读取时的套接字行为的主要内容,如果未能解决你的问题,请参考以下文章

使用 gen_tcp 时的套接字接受率

套接字中没有可用数据时的异步编程模型

从套接字读取时如何处理阻塞的 read() 调用?

在读取缓冲区已满时使用 select 检查可写套接字

连接到 IRC 时的套接字问题

使用套接字时的 AllowAutoRedirect 功能