异步套接字和“静默”断开连接
Posted
技术标签:
【中文标题】异步套接字和“静默”断开连接【英文标题】:Asyncsockets and "silent" disconnections 【发布时间】:2011-03-17 11:25:46 【问题描述】:我一直在使用 cocoaasyncsocket 作为使用 asyncsocket 的 Windows .net 服务器的客户端。我正在使用 ProtocolBuffers 对消息进行编码。这些共同构成了一套很棒的工具。
但是最近我注意到,如果我让客户端长时间连接到服务器 - 好几个小时 - 当我尝试请求数据时,消息似乎已发送但从未到达服务器。我将此称为“无声”断开连接,因为如果出现网络问题,我不会收到通常的断开连接。
我正在处理以下方法以进行调试,但它们都没有被调用:
- (NSTimeInterval)onSocket:(AsyncSocket *)sock
shouldTimeoutReadWithTag:(long)tag
elapsed:(NSTimeInterval)elapsed
bytesDone:(CFIndex)length
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
- (void)onSocketDidDisconnect:(AsyncSocket *)sock
在没有任何通知的情况下,我发现调试起来很棘手。服务器同样没有显示任何断开连接。
谁能指出如何进一步分析这个的方向?
非常感谢。
【问题讨论】:
你有没有找到任何有效的解决方案让套接字长期存活? 【参考方案1】:如果您想知道您的客户端和服务器是否已连接,您必须有心跳或“keepalive”,即交换的应用程序级消息基本上说“你在吗”/“是”。
现在尤其如此,因为许多路由器会默默地丢弃空闲的 TCP 连接。这不是 TCP 的设计目的,但它是生活中的事实。
TCP 可以选择发送连接层心跳或使用 SO_KEEPALIVE 保持活动状态,但历史上存在关于这是否合适的争论。设计者认为由于临时的中间网络问题而丢弃套接字是错误的。如果在此期间没有实际发送数据,则没有理由断开连接。其他人则认为了解这种联系是否良好本身就很重要。如果您期待数据但尚未到达怎么办?你不想知道吗?
最终取决于应用程序。如果“无新信息”是对您的应用程序很重要的事实断言(例如新闻提要、销售订单、市场数据价格变化),您需要检查“无新信息”是否是真实的“无新信息” ” 而不是“连接默默地掉线”。这意味着一个明确的消息。
那么你应该多久发送一次?
这取决于事物的平衡。 1a) 您通常多久获得一次更新? 1b) 什么延迟是可接受的/正常的(例如,如果这是一个过程的一部分,其他步骤通常需要几个小时,那么 5-10 分钟可能是可以接受的)。 2a) 电池和 2b) 心跳导致的数据使用。我怀疑对电池/电源的影响将是至关重要的,但所有这些都需要仔细观察并保持平衡。
毕竟(隧道等),您随时可能失去覆盖范围。只有在平均更新间隔的 0.5 到 5 倍之间没有更新时,我才会运行心跳。因此,如果您预计每分钟 2 次更新,则在空闲 15 秒到 3 分钟的情况下运行心跳 - 判断什么是最好的。如果用户在应用程序中“运行”并在完成后“将其关闭”,那么电池寿命就不是问题,因为他们无论如何都在使用它。如果您要唤醒设备以处理更新,那么电池寿命确实是一个问题。
【讨论】:
我希望这不是答案。这是一个移动应用程序,定期发送“ping”消息似乎很浪费。我应该实现 SO_KEEPALIVE 还是构建自己的协议? 如果您有其他信息可以在心跳期间进行有用的交换,那么请使用应用程序级别的信息。否则 SO_KEEPALIVE 很好,但是您必须使用 SIO_KEEPALIVE_VALS 设置所需的保活间隔,因为默认值为 2 小时,我怀疑这太长了。 我们实现了一个非常简单的应用程序级的,因为 asyncsockets 让它变得如此简单。现在的问题是时机。对于将在移动设备上使用的应用程序,使用的最佳时间间隔是多少? 这取决于事物的平衡。 1a) 您通常多久获得一次更新? 1b) 什么延迟是可接受的/正常的(例如,如果这是一个过程的一部分,其他步骤通常需要几个小时,那么 5-10 分钟可能是可以接受的)。 2a) 电池和 2b) 心跳导致的数据使用。 我怀疑对电池/电源的影响将是至关重要的,但所有这些都需要仔细研究并保持平衡。 这是一个股票交易应用程序,所以延迟非常重要。该应用程序没有任何其他定期运行的功能,只有这个保活过程。我想我需要提出这个问题的方式是,“在发送此 keepalive 之前,我可以等待并且知道我不会断开连接的最长时间是多少?”以上是关于异步套接字和“静默”断开连接的主要内容,如果未能解决你的问题,请参考以下文章
如何处理与 python 套接字的断开连接? (连接重置错误)