是否会发生套接字客户端关闭连接而服务器不知道的情况?

发布于 2024-12-09 17:13:00 字数 100 浏览 0 评论 0原文

套接字客户端是否会关闭连接而服务器不知道这一点? 我在 C# 中的事件 BeginReceive() 上收到了几个错误。 如何检查客户端是否还活着以及在我的程序的哪些位置最好放置此检查?

Can it happen that a socket client closes connection and the server doesen't know this ?
I received several error on the event BeginReceive() in C#.
How to check if the client is still alive and in which places of my program would be better to place this checks ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

﹎☆浅夏丿初晴 2024-12-16 17:13:00

假设您谈论的是 TCP 之上的协议,是的,它可能会发生。 TCP 不需要发送任何数据包来保持连接处于活动状态。因此,如果关闭连接的数据包没有到达服务器,服务器可能会认为客户端仍然存在,即使在客户端关闭连接很久之后也是如此。

因为这是 TCP 的一个众所周知的属性,所以 TCP 之上的每个协议都必须考虑到这一点。因此,如果您只是遵循协议,就不会有问题。

例外情况是协议设计得非常糟糕或者您正在设计协议。如果您正在设计协议,您有很多选择。例如,您可以指定一端必须至少每 10 分钟发送某种消息。您还可以指定另一端在 20 分钟内没有收到任何消息时关闭连接。

Assuming you're talking about a protocol layered on top of TCP, yes it can happen. TCP doesn't require any packets to be sent to keep a connection alive. So if the packets that close the connection don't get through to the server, the server may think the client is still there, even long after the client has closed the connection.

Because this is a well-known property of TCP, every protocol layered on top of TCP has to take this into account. So if you simply follow the protocol, you won't have a problem.

The exceptions are if the protocol is very badly designed or if you are designing the protocol. If you are designing the protocol, you have a lot of choices. For example, you can specify that one end must send some kind of message at least every 10 minutes. And you can specify that the other end should close the connection if it doesn't receive any message for 20 minutes.

淡墨 2024-12-16 17:13:00

使用套接字编程时,有几种“关闭连接”。 (我将使用 BSD 派生的系统调用名称进行套接字操作,我希望它们通过对 C# 的更改保持相似的名称。)

  • 客户端程序使用 shutdown() 关闭套接字或close()。发生这种情况时,TCP 将向您的服务器发送 FIN 数据包。当您尝试读取超出客户端发送的数据的最后一个字节时,这将在服务器中显示为关闭的套接字。下一个read()可能会抛出异常或错误情况。 (因环境而异。)此条件通常适用于轮询式接口(例如 select(2)poll(2)),因此您的标准事件循环处理程序可以发现客户端退出并处理它们。

  • 客户端程序可能会意外退出。在这种情况下,客户端的 TCP 实现可能会发送 FIN 数据包,但它可能不在应用程序输入解析器中的“预期”位置。准备好处理指示应用程序过早终止的零字节读取或 EOF 读取。

  • 客户端主机可能会意外死亡。在这种情况下,客户端的 TCP 实现将无法向您的服务器发送 FIN 数据包,并且您根本不会收到任何客户端连接已终止的通知。您可以启用 TCP SO_KEEPALIVE 套接字选项,但至少 Linux 在发送 keepalive 探测之前默认系统范围内有两个小时的不活动时间。

    如果系统“快速”恢复,您的应用程序将收到 TCP RST 数据包作为响应,如果 状态防火墙配置为DROP与允许或启动的流量流不匹配的数据包。 RST 情况的检测与 FIN 数据包类似。丢弃数据包的静默只能通过应用程序级保活数据包方案来检测。

因此,最好在您可以接受的时间范围内构建某种应用程序级别的 keepalive ping 数据包。 (例如,IRC 使用 PINGPONG 数据包来确保客户端仍然连接到服务器 - 检查之间的时间可由网络管理员配置。

) ping 之间的切换以及接受多少个失败的 ping 数据包在很大程度上取决于您的应用程序 - 您可能愿意在注意到并删除断开连接的客户端之前等待二十分钟,或者您可能希望在仅二十分钟后注意到并删除断开连接的客户端秒。多长时间取决于工作环境(20 秒对于火星探测器来说是不够的,但对于 LAN 连接的第一人称射击游戏视频游戏来说可能太长了十倍)和可用于此类“管理开销”的网络带宽。

There are several kinds of "closed connections" when programming with sockets. (I'll use the BSD-derived system call names for the socket operations, I hope they kept similar names through the changes to C#.)

  • The client program closes the socket using shutdown() or close(). When this happens, TCP will send a FIN packet to your server. This will show up as a closed socket in your server when you try to read beyond the last byte of data sent by the client. The next read() will probably throw an exception or error condition. (Varies by environment.) This condition is usually available to polling-style interfaces (such as select(2) or poll(2)) so your standard event loop handler can discover client quits and handle them.

  • The client program can unexpectedly quit. In this case, the client's TCP implementation will probably send FIN packets, but it might not be in an "expected" place in your application's input parser. Be prepared to handle zero-byte reads or EOF reads that indicate a premature application termination.

  • The client host can unexpectedly die. In this case, the client's TCP implementation won't be able to send a FIN packet to your server and you will not receive any notification at all that the client connection has terminated. You can enable the TCP SO_KEEPALIVE socket option, but at least Linux defaults to a system-wide time of two hours of inactivity before sending the keepalive probes.

    If the system comes back up 'quickly', your application will receive either TCP RST packets in response or silence if a stateful firewall is configured to DROP packets that don't match allowed or initiated traffic streams. The RST case can be detected similar to the FIN packets. The silence of dropped packets can only be detected with an application-level keepalive packet scheme.

So it's best to build in an application-level keepalive ping packet of some sort on a time frame that is acceptable to you. (For example, IRC uses PING and PONG packets to ensure clients are still connected to servers -- the time between checks is configurable by network administrators.)

How long you'll go between pings and how many failed ping packets to accept depends heavily upon your application -- you might be willing to allow twenty minutes to elapse before noticing and removing a disconnected client, or you might want to notice and remove a disconnected client after only twenty seconds. How long depends upon the working environment (20 seconds wouldn't work for a Mars rover but might be ten times too long for a LAN-connected First-Person-Shooter video game) and network bandwidth available for "administrative overhead" like this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文