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

C++ 通过posix套接字发送文件时的零窗口,c++,linux,tcp,sockets,posix,C++,Linux,Tcp,Sockets,Posix,我有一个问题——当我试图通过posix套接字发送大量数据(不管是文件还是一些数据)时,在某个时刻我没有收到我所期望的数据——我使用wireshark来确定是什么导致了错误,我发现,就在我的应用程序崩溃的时候,有标记为红色的数据包说“零窗口”或“零窗口”“窗口已满”向两个方向发送 结果是,应用程序层没有得到send()函数发送的一段数据 我做错什么了吗 编辑: 假设我想发送19232条数据,每条1024字节-在某个随机点(或者根本不发送)我得到的不是第9344个数据包,而是第9345个数据包。我没

我有一个问题——当我试图通过posix套接字发送大量数据(不管是文件还是一些数据)时,在某个时刻我没有收到我所期望的数据——我使用wireshark来确定是什么导致了错误,我发现,就在我的应用程序崩溃的时候,有标记为红色的数据包说“零窗口”或“零窗口”“窗口已满”向两个方向发送

结果是,应用程序层没有得到send()函数发送的一段数据

我做错什么了吗

编辑:


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

在您的网络中,是否也无法发送如此数量的数据包?如果没有,请检查它们如何发送如此数量的数据。

嗯,从我读到的这可能是某种缓冲区溢出(接收方报告接收窗口为零)。只是猜测一下。

零窗口/窗口已满表示TCP连接的一端无法接收更多数据,直到其客户端应用程序读取到已接收的部分数据。换句话说,它是连接的一端告诉另一端”除非我告诉你,否则不要再发送任何数据”

TCP确实处理重传。您的问题可能是:

  • 接收端的应用程序读取数据的速度不够快
  • 这会导致接收TCP向发送TCP报告窗口已满
  • 这反过来会导致发送TCP端的
    send()
    返回
    0
    (未写入字节),或
    -1
    ,并将
    errno
    设置为
    ewoodblock
  • 您的发送应用程序没有检测到这种情况,并且假设
    send()
    发送了您要求发送的所有数据

  • 这会导致数据丢失。您需要修复发送端,以便它处理
    send()
    失败,包括返回一个小于您要求它发送的字节数的值。如果套接字是非阻塞的,这意味着等待
    select()
    在重试之前告诉您套接字是可写的。

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

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


    如果您想粘贴接收方代码,我们可以看一下,但是从您描述的内容来看,您的第9344次读取很可能实际得到的字节数超过了您的数据包大小。您是否检查了从
    recv
    返回的值?

    TCP应该为您这样做……您可以复制/通过部分代码吗?我已经尝试发送了/在4 FC8 x86系统上,使用socket,一个作为服务器,三个客户端接收巨大的文件(比如几GB,带有FILE64选项)。虽然我使用了应用程序级消息库Effo NetMsg()。如果使用TCP,则应用程序send()可以通过协议和send/recv缓冲区控制传输更大的数据包(意味着>MTU)。所以系统应该没有问题。