gpt4 book ai didi

c - 有没有办法检测到 TCP 套接字已被远程对等方关闭,而无需从中读取?

转载 作者:可可西里 更新时间:2023-11-01 02:29:48 25 4
gpt4 key购买 nike

首先,解释一下动机的一些背景知识:我正在研究一个非常简单的基于 select() 的 TCP“镜像代理”,它允许两个受防火墙保护的客户端间接地相互交谈。两个客户端都连接到此服务器,一旦两个客户端都连接上,客户端 A 发送到服务器的任何 TCP 字节都会转发到客户端 B,反之亦然。

这或多或少是可行的,但有一个小问题:如果客户端 A 连接到服务器并在客户端 B 连接之前开始发送数据,则服务器没有地方可以放置数据。我不想将它缓冲到 RAM 中,因为那样最终可能会占用大量 RAM;而且我也不想只删除数据,因为客户端 B 可能需要它。所以我选择了第三个选项,即在客户端 B 也已连接之前,不要在客户端 A 的套接字上选择 ()-for-read-ready。这样客户端 A 就会阻塞,直到一切准备就绪。

这或多或少也有效,但在客户端 A 的套接字上不选择读取就绪的副作用是,如果客户端 A 决定关闭他与服务器的 TCP 连接,服务器不会收到有关的通知这个事实 - 至少,直到客户端 B 出现并且服务器最终在客户端 A 的套接字上选择读取就绪,读取任何未决数据,然后获得套接字关闭通知(即 recv() 返回 0) .

如果服务器有某种方式(及时)知道客户端 A 何时关闭了他的 TCP 连接,我会更喜欢它。有办法知道吗?在这种情况下轮询是可以接受的(例如,如果存在这样的函数,我可以让 select() 每分钟唤醒一次并在所有套接字上调用 IsSocketStillConnected(sock))。

最佳答案

如果你想检查套接字是否真的关闭而不是数据,你可以在 recv() 上添加 MSG_PEEK 标志来查看数据是否到达或者你是否得到 0 或一个错误。

/* handle readable on A */
if (B_is_not_connected) {
char c;
ssize_t x = recv(A_sock, &c, 1, MSG_PEEK);
if (x > 0) {
/* ...have data, leave it in socket buffer until B connects */
} else if (x == 0) {
/* ...handle FIN from A */
} else {
/* ...handle errors */
}
}

即使 A 在发送了一些数据后关闭,您的代理可能希望在将 FIN 转发给 B 之前先将该数据转发给 B,因此在读取之后就知道 A 已经在连接上发送了 FIN 是没有意义的它发送的所有数据。

直到双方都发送 FIN 之后,TCP 连接才会被视为关闭。但是,如果 A 强行关闭了它的端点,直到您尝试在其上发送数据并收到 EPIPE(假设您已抑制 SIGPIPE)后,您才会知道这一点.


在稍微阅读了您的镜像代理应用程序之后,由于这是一个防火墙穿越应用程序,您似乎实际上需要一个小型控制协议(protocol)来允许您验证这些对等点实际上是否被允许相互交谈。如果你有一个控制协议(protocol),那么你有很多可用的解决方案,但我提倡的是让一个连接将自己描述为服务器,另一个连接将自己描述为客户端。然后,如果不存在服务器来建立连接,您可以重置客户端的连接。您可以让服务器等待客户端连接直至超时。服务器不应启动任何数据,如果它在没有连接的客户端的情况下启动,您可以重置服务器连接。这消除了为死连接缓冲数据的问题。

关于c - 有没有办法检测到 TCP 套接字已被远程对等方关闭,而无需从中读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17705239/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com