背景:
我们有一个客户端/服务器应用程序,它使用与服务器的持久连接。
基准测试表明,使用已经打开的连接比花费大量时间(2.5 秒)建立新连接(加密)要快很多倍。
不幸的是,旧的连接可能已经过时了。
有没有办法等待发送消息的系统级结果[ACK 或错误]?
等待读取然后获取流的结尾会导致混乱。
我知道消息可能会被分解成数据包。知道消息的任何部分是否被确认或全部都被确认同样适合我的目的。这里有趣的问题是陈旧的连接。
不幸的是,旧的连接可能已经过时了。
在这种情况下,您最终会在写入时遇到异常。
有没有办法等待发送消息的系统级结果[ACK 或错误]?
不。
等待读取然后获取流的结尾会导致混乱。
迷惑谁?处理混乱是代码的工作。如果你得到一个意外的 EOS,对端已经关闭了连接,或者中间防火墙有,在这种情况下你必须处理它。
我知道消息可能会被分解成数据包。
完全无关。你也无法控制它或它的任何可见性。你得到的是一个被 EOS 或异常终止的字节流。
知道消息的任何部分是否被确认或全部都被确认同样适合我的目的。
不,它不会。ACK 仅表示它已到达对等方的 TCP/IP 堆栈。您的应用程序感兴趣的是它是否已进入对等应用程序,并且只有对等应用程序可以通过应用程序协议级别的 ACK 告诉您。TCP/IP ACK 在这里没有帮助。
这里有趣的问题是陈旧的连接。
这是一个相当微不足道的问题。您可以在代码中检测到它,并且可以同上处理它。几十年来,数据库供应商一直在做这些事情。不是火箭科学,也没有什么需要了解 TCP ACK 的知识。
如果连接不再可行,TCP 堆栈本身不太可能及时告诉您(除非它在本地中断并且操作系统可以向堆栈报告本地故障)。由于重新传输超时(请参见此处)以及在写入之前可能需要“相当长的时间”的任何情况,都会返回失败以指示连接已断开。当然,这是设计使然,只是设计与您想要做的不一致。
您可以尝试使用 TCP 保持活动,但恕我直言,这些并不值得付出努力,如果可能的话,您最好实现某种形式的应用程序级 ACK,以便您可以使您的应用程序级协议尽快发回响应它会从您那里获取一些数据。如果您不能这样做,并且您的请求会从连接的另一端引发响应,那么您可以简单地设置一个计时器,该计时器基于您准备等待响应的时间,然后再假设连接已死。计时器到期后,您将关闭连接并建立一个新连接。
可能您可以启动新连接尝试并在旧连接上发送请求,如果新连接在您得到旧连接响应之前可用,那么您可以在新连接上发送请求并关闭旧的...当然,这取决于您的应用程序能够处理这种事情。
最后,如果连接由于不活动而中断,那么也许您可以将应用程序级别的 ping 添加到您的协议中,该协议可以设置为每隔一段时间发送一条消息到 a) 确保连接处于活动状态和 b) 停止路由器或防火墙从认为连接已死。
在处理 TCP 通信的层,您不必担心 ACK。这是第 3 层及以下的工作。对于您的协议,请始终发出命令/响应请求。无论成功还是错误,都应有响应。将无响应解释为成功是危险的,因为中断的沟通也会导致同样的效果。
我不知道你说的陈旧是什么意思。因为 TCP 是面向连接的协议,所以连接是否存在。因此我不太明白你有什么麻烦:如果你失去了连接,你必须努力创造一个新的。