1

我一直在使用 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

没有任何通知,我发现调试起来很棘手。服务器同样没有显示任何断开连接。

谁能指出我如何进一步分析这个方向?

非常感谢。

4

1 回答 1

3

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

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

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

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

那么你应该多久发送一次呢?

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

毕竟,您可能随时失去覆盖范围(隧道等)。只有在平均更新间隔的 0.5 到 5 倍之间没有更新时,我才会运行心跳。因此,如果您预计每分钟 2 次更新,则在空闲 15 秒到 3 分钟的情况下运行心跳 - 判断什么是最好的。如果用户在应用程序中处于“实时”状态并在完成后“将其关闭”,那么电池寿命就不是问题,因为他们无论如何都在使用它。如果您要唤醒设备以处理更新,电池寿命确实是一个问题。

于 2011-03-17T11:36:56.837 回答