【问题标题】:recovering transmission from lost TCP connection从丢失的 TCP 连接中恢复传输
【发布时间】:2013-03-21 14:18:13
【问题描述】:

我正在开发用 C 语言为 Linux 编写的客户端服务器应用程序,我正在使用 TCP 将数据复制到多个从属副本,我想知道如何处理某些副本的意外临时关闭(可能是unix 进程或硬件电源关闭)。

当我向内核发出 write() 系统调用时,成功返回意味着数据已复制到套接字,但并不意味着接收端得到数据。如果目标断电然后再通电,则必须从丢失数据的点将数据重新发送(在建立新的 TCP 连接后)到副本。

假设我正在处理大量数据并且我不保留已发送的数据(即 write() 系统调用返回成功)。我只保留待发送的数据。

当副本从意外关闭中恢复并再次连接时,我如何从内核获取已写入套接字但在目标主机上尚未“确认”的数据?

或者换句话说,我如何从 TCP 连接丢失中恢复并从停止点重新建立客户端和服务器之间的传输?

【问题讨论】:

    标签: c linux network-programming


    【解决方案1】:

    您需要在 TCP 之上添加另一层抽象。在发送完每条数据之后(TCP 保证它会完整有序地到达那里),让另一端的进程在您自己的更高级别协议中发送它自己的 ACK(不管是什么——不管它是什么) ACK\0"、"GOT\n" 或其他任何东西)。在另一端(发起者),读取此数据。如果它通过良好而没有错误,一切都很好。如果您收到错误 - 检查类型。如果你得到 ECONNRESET,这意味着远程端已经死了。由此,您可以做出相应的回应。等到可以重新连接,然后重新发送数据。

    【讨论】:

    • 如果我必须在 TCP 本身之上实现我自己的 TCP,这让我觉得在这种情况下 UDP 可能会更好。
    • @Nulik:不! (请不要使用 UDP!请!)。 UDP 不保证任何ever 都可以到达anywhere,或者它以any 的顺序到达那里,或者它甚至是sent 首先!这不是 TCP 之上的 TCP,这是一个利用 TCP 所有特性的小型应用程序级协议。请不要重新实现 TCP。操作系统的实现已经过数百名专家的磨练和完善。不要试图重做他们的工作。
    【解决方案2】:

    没有办法通过标准 API 做你想做的事。

    一种解决方案可能是让您的客户端定期将收到并验证写入磁盘的运行总字节数发回,然后在服务器上保留一个已发送但未确认数据的缓冲区。然后当客户端重新连接时,它会发送最后一个好的计数,服务器知道从哪里开始重新传输。

    【讨论】:

      【解决方案3】:

      TCP 会处理 TCP 所需的序列号,您不能在应用程序级别大量使用这些序列号

      您需要在应用程序级别进行一些顺序控制。

      在您的情况下,您可以为您发送的每个数据块分配一个编号。目的地需要持续跟踪它收到的最后一个块号。从意外关闭启动时,目标需要返回它处理的最后一个块号,然后您从那里开始发送。

      如何从内核中获取已写入套接字的数据,但目标主机上尚未“确认”?

      即使你可以,这也不够。目标主机很可能已经确认了数据,但无论出于何种原因,确认都可能丢失或从未发送,但目标应用程序可能已经接收并处理了该数据。所以如果你在这种情况下使用 TCP 序列号,你最终会得到重复的数据。

      另一种情况是 TCP 发回数据的 ack,而目标应用程序在读取该数据时崩溃/关闭,但就在它将数据写入磁盘之前。所以你最终会丢失数据。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-09
      相关资源
      最近更新 更多