如何使用 select(2) 等待套接字关闭以进行写入

How to wait with select(2) for socket closed for writing

提问人:urs 提问时间:11/17/2023 最后编辑:Uselessurs 更新时间:11/18/2023 访问量:27

问:

有没有办法等待对等方调用其套接字或完全关闭其套接字的套接字?select(2)shutdown(SHUT_RD)

尝试写入这样的套接字将返回 (Broken Pipe)。我希望在我尝试写作之前收到有关此情况的通知。EPIPE

在服务器中,我用来等待通过TCP连接的新订阅者,以及将其他FDS上的输入转发给订阅者。如果订阅者关闭了其连接,或者仅关闭了其 READ 端,我想立即关闭我的套接字端并释放相关资源。select(2)

我尝试等待异常,但没有报告关闭的套接字。等待订阅者在套接字上的读取也不起作用,因为等待读取只会在套接字完全关闭时返回,并且会随 EOF 一起返回。select(2)read(2)

套接字 选择 EOF fclose

评论

0赞 Useless 11/17/2023
只需切换到使用并查找(和/或如果可用)pollPOLLHUPPOLLRDHUP
3赞 Steffen Ullrich 11/17/2023
@Useless:如果对等方关闭了套接字或SHUT_WR,则会触发此操作,但不会按照 OP 的要求使用 SHUT_RD。
0赞 Useless 11/18/2023
你说得很对。我从未见过有人真正使用过,我也没有想到shutdown(SHUT_RD)

答:

1赞 Steffen Ullrich 11/17/2023 #1

关闭套接字以读取 () 是一个纯粹的本地操作,它不会以任何方式传播到对等体。所以不可能等待这个。只有关闭用于写入 () 的套接字才会通过发送 FIN 进行传播。这与完全关闭套接字相同,因此对等方无法将其与 区分开来。SHUT_RDSHUT_WRSHUT_WR

等待对等方关闭套接字或等待套接字可读是相同的。在这种情况下,它不会返回任何数据,而是返回 0,即没有数据但没有错误。SHUT_WRrecv

但是,即使完成时节点会发出通知(同样,没有这样的通知),在编写之前依赖它实际上并不安全。因为此通知需要一些时间才能从对等方到达,即存在不可避免的竞争条件。SHUT_RD

因此,您需要构建代码,以便它可以正确处理。EPIPE

评论

0赞 urs 11/18/2023
我已经有处理 EPIPE 的代码了。我只认为我可以在尝试写入之前更早地释放服务器中的资源,即当客户端关闭其套接字甚至只SHUT_RD时。当远程插座关闭时,我将添加看到 EOF 的操作,这也应该没问题。谢谢你的回答。