异步套接字和“静默”断开连接

时间:2011-03-17 11:25:47

标签: cocoa sockets asyncsocket casyncsocket

我一直使用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 个答案:

答案 0 :(得分:3)

如果您想知道您的客户端和服务器已连接,您必须拥有心跳或“保持活动”,即基本上交换的应用程序级别消息“你在那里”/“是”。

现在尤其如此,因为许多路由器将静默地丢弃空闲的TCP连接。这不是TCP的设计目标,但这是生活中的事实。

TCP可以选择使用SO_KEEPALIVE发送连接层心跳或keepalive,但历史上有一个关于这是否合适的争论。设计人员认为,由于暂时的中间网络问题而丢弃套接字是错误的。如果在此期间没有实际发送数据,则没有理由放弃连接。其他人认为,了解连接是否良好本身就很重要。如果您期待数据但尚未到达,该怎么办?你不想知道吗?

最终取决于应用程序。如果“没有新信息”是对您的应用程序很重要的事实断言(例如新闻提要,销售订单,市场数据价格变化),您需要检查“没有新信息”是否真实“没有新信息” “不是”连接无声地丢弃“。这意味着一条明确的信息。

那你多久发一次呢?

这取决于事物的平衡。 1a)您经常获得更新的频率是多少? 1b)什么延迟是可接受/正常的(例如,如果这是一个过程的一部分,其他步骤通常需要几个小时,那么5-10分钟可能是可接受的)。 2a)电池和2b)由于心跳导致的数据使用。我怀疑对电池/电源的影响至关重要,但所有这些都需要仔细查看并保持平衡。

在所有(隧道等)之后,您可能会在任何时候失去保险。只有在平均更新间隔的0.5到5倍之后没有更新时,我才会运行心跳。因此,如果您希望每分钟更新2次,请在闲置15秒至3分钟时运行心跳 - 判断什么是最佳状态。如果用户在应用程序中处于“实时”状态并且在完成时“关闭”,则电池寿命不是问题,因为他们无论如何都在使用它。如果您唤醒设备以处理更新,则电池寿命确实存在问题。