【问题标题】:how does non-blocking tcp socket notify application on packets which fail to get sent.非阻塞 tcp 套接字如何通知应用程序发送失败的数据包。
【发布时间】:2014-06-04 01:29:03
【问题描述】:

我正在为 linux 系统开发一个非阻塞 C tcp 套接字。我读过在非阻塞模式下,如果没有错误,“发送”命令将立即返回“发送的字节数”。我猜这个返回的值实际上并不意味着这些数据已经被传递到目的地,而是数据已经被传递到内核内存以供进一步处理和发送。

如果是这样的话,我的应用程序如何知道内核真正发送了哪个数据包到另一端,假设网络连接有一些问题并且内核决定在一段时间内重试几次后才放弃几分钟后?

我问是因为我希望我的应用程序稍后再重新发送那些失败的数据包。

【问题讨论】:

    标签: c linux sockets tcp


    【解决方案1】:

    如果是这样,我的应用程序如何知道哪个数据包有 确实被内核发送到另一端,假设 网络连接出现问题,内核决定放弃 只是在几分钟后重试几次?

    您的应用程序不会知道,除非它能够重新联系接收应用程序并询问接收应用程序它之前收到了什么数据。

    请记住,即使阻塞 I/O,您的应用程序也不会阻塞,直到远程应用程序接收到数据——它只会阻塞,直到内核的传出数据缓冲区中有一些空间来保存您的字节要求 TCP 堆栈发送()。因此,即使阻塞 I/O,您也会面临同样的问题。

    还请记住,您传递给 send() 的字节数组与 TCP 堆栈发出的 TCP 数据包没有保证的一对一对应关系。 TCP 堆栈可以随意将字节打包到 TCP 数据包中(例如,来自多个 send() 调用的数据可以在单个 TCP 数据包中结束,或者来自单个 send() 调用的数据可以在多个TCP 数据包,或您能想到的任何其他组合)。根据网络条件,TCP 堆栈可以并且确实以各种不同的方式打包东西,它们唯一的承诺是字节将以 FIFO 顺序接收(如果它们完全被接收)。

    无论如何,你的问题的答案是:你无法知道,除非你稍后询问接收程序它得到了什么(或没有得到什么)。

    【讨论】:

    • 或者如果接收程序对你发送的数据发送一个确认回复。
    【解决方案2】:

    TCP 在内部负责重试,应用程序不需要对其进行任何特殊处理。如果您希望确认 TCP 堆栈的另一端收到了数据包,则可以将发送套接字缓冲区 (setsockopt(SOL_SOCKET, SO_SNDBUF)) 设置为零。在这种情况下,内核使用您的应用程序缓冲区来发送数据,并且仅在 TCP 收到此数据的确认后才释放。这样就可以确认数据被推送到 TCP 栈的接收端了。它不确认应用程序已收到数据。您需要在协议中添加应用层确认,以确认数据已到达接收应用程序。

    【讨论】:

    • Linux documentationSO_SNDBUF 没有提到零作为受支持的值。它确实说:“当使用 setsockopt(2) 设置时,内核将这个值加倍(为簿记开销留出空间)......这个选项的最小(加倍)值是 2048”。
    • 在这篇文章中微软谈到了它。 support.microsoft.com/kb/214397/EN-US Socket 规范对所有操作系统都是通用的,所以我希望 linux 会有类似的行为。
    • @dvasanth 请为此声明提供引用。我可以相信在某些平台上可以将SO_SNDBUF 设置为零,但不会导致 TCP '使用应用程序缓冲区',或者它会导致应用程序阻塞,直到收到 ACK。您的新引文不支持这些说法。
    • AFD 是winsock 的内核模式组件。它在注册表 DefaultSendwindow 中有一个可配置的值,可以被 SO_SNDBUF 覆盖。如果发送缓冲区中有足够的发送缓冲区空间,AFD 只需将发送数据复制并指示成功给应用程序。如果缓冲区已满,则对下面的 TCP 传输驱动程序进行同步 IO,阻塞应用程序中的发送 API。如果发送缓冲区为零,则应用程序可以保持流量控制。检查以下链接以获取 AFD 发送窗口大小信息smallvoid.com/article/winnt-winsock-buffer.html
    猜你喜欢
    • 2011-05-31
    • 2013-09-16
    • 1970-01-01
    • 2014-11-01
    • 1970-01-01
    • 2010-12-05
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多