通过posix套接字发送文件时的零窗口

时间:2009-11-27 13:31:59

标签: c++ linux tcp sockets posix

我有一个问题 - 当我试图通过posix套接字发送大量数据时(无论文件或某些数据无关紧要)在某些时候我没有得到我所期望的 - 我使用wireshark来确定导致错误的是什么,我发现,正是在我的应用程序中断时,有两个方向发送的标记为红色的数据包说“零窗口”或“窗口已满”。

结果是,应用层没有得到send()函数发送的数据。它虽然得到了下一部分......

我做错了吗?

编辑:

让我们说我想发送19232个数据,每个1024字节 - 在某个随机点(或根本不发送)而不是第9344个数据包我得到第9345个。我没有实现任何重传协议,因为我认为TCP是为我做的。

4 个答案:

答案 0 :(得分:1)

Zero Window / Window Full表示TCP连接的一端无法接收更多数据,直到其客户端应用程序读取已收到的某些数据为止。换句话说,它是连接的一面告诉另一方“除非我告诉你,否则不再发送任何数据”。

TCP 处理重新传输。你的问题很可能是:

  1. 接收方的应用程序不能足够快地读取数据。
  2. 这会导致接收TCP将Window Full报告给发送TCP。
  3. 这反过来导致发送TCP端的send()返回0(没有写入字节),或-1 errno设置为EWOULDBLOCK
  4. 您的发送应用程序未检测到此情况,并假设send()已发送您要求发送的所有数据。
  5. 这会导致数据丢失。您需要修复发送方以使其处理send()失败,包括返回小于您要求它发送的字节数的值。如果套接字是非阻塞的,这意味着等到select()告诉您套接字可写之后再重试。

答案 1 :(得分:1)

首先,TCP是字节流协议,而不是基于数据包的协议。仅仅因为您发送了一个1024字节的块并不意味着它将以这种方式接收。如果你正在快速填充管道以获得零窗口条件(即,接收缓冲区或发送缓冲区中没有更多空间)那么接收器代码很可能在某一时刻能够读取远比你的“数据包”的大小更多。

如果您没有特别请求非阻塞套接字,那么sendrecv都将以零窗口/窗口满状态阻塞,而不是返回错误。

如果你想粘贴接收器端的代码,我们可以看看,但从你所描述的内容来看,你的第9344次读取实际上可能会获得比数据包大小更多的字节。您是否检查了从recv返回的值?

答案 2 :(得分:0)

您的网络iperf是否也无法发送此数量的此类数据包?如果没有,请检查他们如何发送这些数据。

答案 3 :(得分:0)

嗯,从我在Wikipedia上看到的,这可能是某种缓冲区溢出(接收器报告零接收窗口)。只是一个猜测。