【问题标题】:A question on TCP connection buffers关于 TCP 连接缓冲区的问题
【发布时间】:2010-11-10 17:30:06
【问题描述】:

Linux。

我在两台计算机之间有一根以太网电缆。一个简单的 C 语言服务器-客户端程序,用于将文件从客户端传输到服务器。客户端从文件中读取 100 字节的数据并发送给服务器,然后等待 2 秒再发送下一个数据包。

当客户端发送数据时,我拔掉了服务器端的以太网电缆,由于连接中断,我期待客户端会出现一些错误。但是客户端继续将数据写入管道,服务器没有收到任何东西(但仍在等待接收)。客户端发送了整个文件并停止了。现在,我再次连接以太网电缆,服务器接收客户端发送的所有数据。这怎么可能?数据包是否存储在某个缓冲区中并在连接建立时再次发送?

抱歉,拖得太长了。

【问题讨论】:

    标签: c networking tcp


    【解决方案1】:

    TCP 的全部意义在于提供可靠的数据传输尽管下面有一个不可靠的网络。基本上,它的工作方式是 TCP 只考虑从远程机器收到确认包后发送的数据;在那之前,内核将数据存储在本地。它的缓冲时间可能会很长,这取决于/proc 中的一系列设置以及测量的网络参数。

    edit:应用可以使用SIOCOUTQ ioctl 检查未完成发送队列的大小;请参阅 tcp(7) 联机帮助页。同一手册页也讨论了错误处理。

    如果您希望该数据丢失而不是缓冲,请使用 UDP。

    【讨论】:

    • 没错。这也是我的理解。我不希望数据丢失。我想要一个可靠的连接。现在它存储在内核中,由于客户端程序没有收到任何错误,他很高兴地发送整个文件并退出。现在让我们说,连接不会被恢复,TCP 将释放内核缓冲区而客户端不知道这一点。这里如何保持可靠性?
    • @Blacklabel:您的应用会看到连接重置,因此客户端可以知道。如果连接被重置,则无法保证数据已交付。不幸的是,所有的抽象都泄漏了;这就是所谓的“两将问题”
    • @Blacklabel:您还应该考虑,即使远程机器已经接收并确认了数据,它也会位于远程机器的 TCP 接收缓冲区中,直到应用程序请求它。如果远程应用程序崩溃,或者无法处理数据...
    • @Derobert。非常感谢。我明白了:)。另一个业余问题,如何在 C 中找到连接是否重置?
    • @Blacklabel:您不想要禁用此功能。您想要的是让您的发送应用程序等到接收 应用程序 通知它数据已被接收并保存到磁盘(或以其他方式处理)。 “正确接收”是应用层属性,不能在TCP层处理。
    【解决方案2】:

    是的。根据配置,它甚至可能会等待一段时间以查看是否可以恢复连接。甚至,tcp 超时可能是几分钟...注意here 例如参数tcp_fin_timeout 和其他与超时相关的参数。

    【讨论】:

    • 感谢您的宝贵时间。该链接很有用。但我在这里遗漏了一些东西。这里失去了可靠性。如果 TCP 缓冲它,然后如果连接没有恢复,它最终会丢弃数据包。现在客户端不知道这一点,它认为它发送了数据包。
    • 不完全是。如果无法发送数据包(超时),则会向客户端发送错误(关闭连接)。如果可以发送它们,即使您断开连接,它们也会发送,然后再连接,因此不会出错。包丢失总是意味着返回给客户端的错误。
    • 不,它没有:客户端可能已经关闭了套接字,因此在这种情况下无法传递错误。一般来说,您无法知道最终传输已经到达。这就是所谓的两军问题。
    【解决方案3】:

    在 Linux 上,您可以通过运行查看内核维护的发送队列和超时:

    netstat -tanpo
    

    当连接突然终止时,由于错误或超时,客户端可以通过检查write()shutdown()close()的返回值来注意到。

    【讨论】:

      猜你喜欢
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 2016-01-10
      • 1970-01-01
      • 1970-01-01
      • 2015-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多