c# - 在 Internet 上保持 TCP/IP 连接的套接字保持事件状态——什么时候?如何?多少钱?

标签 c# sockets tcp

更新:如果您想省去冗长的序言,请跳至答案。

TCP/IP 连接 KeepAlives 指定为至少每两小时一次:https://www.rfc-editor.org/rfc/rfc1122#page-101 .问题是这是写于 1989 年的,并且担心发送额外的 KeepAlive 数据包的成本!然而,它仍然是大多数操作系统根据规范在一段时间不活动后向连接的套接字发送 KeepAlives 的默认时间!当然,现在大多数连接在此之前超时,如果处于非事件状态,并且如果通过 Internet 连接到对等点,则在此之前您不知情(尽管设置的超时高于此时间 - 我怀疑是因为它们之间的路由器表不会打扰保持它还活着——我一直想知道泄露的最后一条消息去了哪里……更新:原因是可能在您或远程主机端的“路由器”是“有状态的”并且连接感知和在一段时间不活动后断开连接——你通过互联网的路由器不能断开你的连接——它们不关心——数据包只是发送到它必须去的地方)。所以我看到了 2 种常见的解决方案来保持 Internet 上的连接:

  1. 忽略(编辑: 正如我所指出的,这并不是忽略规范,它只是更改默认值)规范并将系统范围内的 KeepAlive 间隔更改为低于 2 小时,或者2) 实现您自己的“KeepAlive”系统,定期轮询对等方。

无论哪种方式;什么是合适的时间段(发送 KeepAlive 的不活动时间段)?我已经看到了从 1 秒到默认 2 小时的所有内容。看来这个数字已经不值一提了……如果我有一个客户端应用程序可能从世界上的任何地方进行连接,那么安全和合理的期限是多少(我想要一个单一的持久连接)?通过 Internet 连接到世界另一端许多跳远的对等点时,连接会在 301 秒后终止(尽管您只有在尝试发送内容时才知道),因此将时间段设置为 300 秒似乎是一个神奇的数字 -我在死亡前 1 秒获得 KeepAlive - 这个间隔从未让我失望过..但它安全吗?

编辑:这个特定的连接是在 C# 3.0 中实现的,所以欢迎编写代码。

最佳答案

何时

当你想防止连接断开时。

如何

通过发送 TCP/IP KeepAlives 或自己发送一些东西,在一段时间不活动后发送一些东西(推荐,因为设置发送 TCP/IP KeepAlives 的时间段将在系统级别应用于所有连接的套接字,而不是在应用层)。

多少

一根绳子有多长?首先你要明白为什么会掉线:

连接断开的原因是:

“有状态”和连接感知的家庭/商业“路由器”和防火墙往往会在一段时间不活动后断开外部 TCP 连接

所以它与您的应用程序或 TCP/IP 本身无关,而是与您的连接所经过的硬件或软件有关。您可以对典型的不活动时期进行一些研究,在这些时期您可能会经历家庭/商业设备/软件断开连接(参见下面的列表)。但是,如果对等点可能是 Internet 上的任何用户:

最终,如果您不知道他们通过什么设备/软件:允许客户端设置他们自己的不活动时间(在该时间发送一些东西以保持连接有效)。

或者以较短的时间间隔(不活动)发送 KeepAlives(或您的等价物)以适应所有情况(尽管不必要的流量是一件坏事,现在每隔几秒不活动就增加一个数据包是一个下降海洋,移动网络除外)。但请注意,根据 TCP/IP 规范,它应该在临时中断后仍然存在,因此将其设置得太低可能会产生无法在临时中断后幸存下来的不良影响,来自 http://aplawrence.com/Bofcusm/2426.html :

The down side of tightening the keepalive parameters is that you also sharply limit TCP's resilience in the face of cable outages. A session whose both ends are alive and ready to run normally stays alive even if an intermediate cable or router is disconnected for a few minutes. If you've told the server to frantically send keepalives, it will notice a cable break and disconnect sessions that would otherwise have survived nicely.

但是,如果您无论如何都在进行一些通信,您就会遇到中断,所以您必须处理这个问题,我认为这种担忧已经过时,因为今天不会出现临时中断(它们更有可能是永久性的 - 电缆被拔掉)持久连接(与狡猾的拨号相反)。如果发生中断,您可能想要重新建立连接(例如 RDP)或不重新建立连接(例如 Telnet)。

一些关于常见应用程序使用的研究:

App    |    KeepAlive sent after    |    configurable    | ref
--------------------------------------------------------------
Telnet |    600 seconds             |          Y         | http://www-01.ibm.com/support/docview.wss?uid=nas14adccb91a24d9ed28625694900513857
MS RDP |    ?

还有一些关于哪些设备/软件会丢弃非事件连接以及何时丢弃的研究:

Device/SW                |    dropped after    |    configurable    | ref
--------------------------------------------------------------
Windows 2003 Firewall    |    24 hours         |          ?         | http://technet.microsoft.com/en-us/library/cc755604(WS.10).aspx
SonicWall TZ100/200      |     5 mins          |          Y         |  http://www.sonicwall.com/downloads/SonicWALL_TZ_100_200_Series_Getting_Started_Guide.pdf
Netgear FR114P           |     5 mins          |          N         | http://www.broadbandreports.com/forum/remark,4182300
Cisco ASA                |     1 hour          |          Y         | http://www.cisco.com/c/en/us/td/docs/security/asa/asa91/configuration/firewall/asa_91_firewall_config/conns_connlimits.html

为了所有人的利益,请编辑/完善这些列表。

关于c# - 在 Internet 上保持 TCP/IP 连接的套接字保持事件状态——什么时候?如何?多少钱?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3907537/

相关文章:

从两个线程在同一个阻塞套接字上调用 recv()

c++ - 使用 RAW_SOCKET 读取 TCP header 并管理 TCP 连接

c# - 记录对象的内存使用情况

javascript - 如何更改日期选择器语言

C# 套接字发送和接收的字节顺序

python - 客户端关闭时服务器崩溃

c# - 异步 TCP 读取期间的 Stackoverflow

java - TCP JSON 命令未到达

c# - 没有编码的 ASP.NET MVC Razor 渲染

c# - MD5 哈希在 C# 和 Objective C 中不相似