【发布时间】:2010-10-12 07:19:28
【问题描述】:
在标准的 tcp 实现中(例如,在 bsd 上),有没有人知道是否有可能找出远程主机已经确认了多少字节?在套接字上调用 write() 会返回写入的字节数,但我相信这实际上意味着可以放入 tcp 缓冲区的字节数(不是写入网络的字节数,或确认的字节数)。或者我错了……
谢谢!
【问题讨论】:
在标准的 tcp 实现中(例如,在 bsd 上),有没有人知道是否有可能找出远程主机已经确认了多少字节?在套接字上调用 write() 会返回写入的字节数,但我相信这实际上意味着可以放入 tcp 缓冲区的字节数(不是写入网络的字节数,或确认的字节数)。或者我错了……
谢谢!
【问题讨论】:
当你有 NODELAY=false (这是默认值)时,当你用比 TCP 窗口少的字节调用 send() 时,字节并没有真正立即发送,所以你是对的。操作系统会稍等片刻,看看你是否调用了另一个 send(),以便只使用一个数据包来传输组合数据,并避免浪费 TCP 标头。
当 NODELAY=true 时,数据会在您调用 send() 时传输,因此您可以(理论上)依靠返回值。但由于增加了网络效率低下,不建议这样做。
总而言之,如果不需要绝对精度,即使 NODELAY=true,也可以使用 send() 返回的值。该值不会反映即时现实,但会在几毫秒后反映(但还会检查丢失的连接,因为您发送的最后一个数据块可能已丢失)。一旦连接正常终止,您就可以相信所有数据都已传输。如果不是,您之前就会知道 - 要么是因为连接突然断开,要么是因为您收到了与数据保留相关的错误(或任何其他错误)。
【讨论】:
我不知道有什么方法可以得到这个,而且它可能对你没有用。
假设您想知道主机接收了多少数据,以便在连接丢失并重新连接后,您可以再次从那里开始发送。因此,已确认的数据仅由操作系统确认!它并不表示你的程序在另一端收到了哪些数据;根据那里的 TCP 接收缓冲区的大小,您的程序可能落后数百 KB。如果您想知道那里的程序已接收到和多少数据“使用”,然后让它发送应用程序级 ACK
【讨论】:
我认为你错了,尽管这是我想先看看具体实施的地方之一,然后我才会赌上大笔的钱。但是,请考虑 TCP 连接的情况,在原始握手后立即断开连接。如果返回的字节数只是缓冲的数量,则可能显然已经写入了许多字节,但它们仍未传递;这将违反 TCP 的交付保证属性。
但请注意,这仅适用于 TCP;并非 IP 中的所有协议都提供相同的保证。
【讨论】:
通过使用ioctl(fd, TIOCOUTQ, &intval); 将传出队列放入intval,您可能对TCP 有一些运气。这将是保留在队列中的总长度,包括“由应用程序写入”但尚未发送。这仍然是我目前能想到的最佳近似值。
【讨论】: