本地主机上的 recv() 数据丢失

Posted

技术标签:

【中文标题】本地主机上的 recv() 数据丢失【英文标题】:recv() data loss on localhost 【发布时间】:2015-07-07 09:29:09 【问题描述】:

我正在构建一个 P2P 文件共享程序,我可以在连接到我的 Wifi 路由器的计算机之间传输文件。 但是,当我在具有本地主机地址的计算机上运行它时,我的程序的发送方部分成功地将所有数据发送到接收方程序,但我的接收方没有获得所有数据。我在我机器上的单独端口上运行这两个。当我在不同的机器上运行发送器和接收器时,不会出现此问题。

这是我的接收代码 sn-p

    while ((len = recv(welcomeSocket, buffer, BUFSIZ, 0)) > 0 && remain_data > 0)
    
            fwrite(buffer, sizeof(char), len, received_file);
            remain_data -= len;
            fprintf(stdout, "Receive %zd bytes and we hope :- %d bytes\n", len, remain_data);

    

这是我的发送代码 sn-p

     while (((sent_bytes = sendfile(fds[i].fd, fd, offset, BUFSIZ)) > 0) && (remain_data > 0))
    
            fprintf(stdout, "Server sent %u bytes from file's data, offset is now : %jd \n", sent_bytes, (intmax_t)offset);
            remain_data -= sent_bytes;
            fprintf(stdout, "remaining data = %d\n", remain_data);
    

发送者部分的输出是

Server sent 8192 bytes from file's data, offset is now : 0 
remaining data = 30292
Server sent 8192 bytes from file's data, offset is now : 0 
remaining data = 22100
Server sent 8192 bytes from file's data, offset is now : 0 
remaining data = 13908
Server sent 8192 bytes from file's data, offset is now : 0 
remaining data = 5716
Server sent 5716 bytes from file's data, offset is now : 0 
remaining data = 0

接收端的输出是

Receive 256 bytes and we hope :- 38228 bytes
Receive 8192 bytes and we hope :- 30036 bytes
Receive 8192 bytes and we hope :- 21844 bytes
Receive 8192 bytes and we hope :- 13652 bytes
Receive 5716 bytes and we hope :- 7936 bytes

再一次,在不同的机器上运行这些程序并且recv() 获取所有数据时不会发生这种情况。 localhost 的通信路径是否如此之快,以至于 recv() 无法处理数据并因此错过了一些数据?

谢谢

【问题讨论】:

猜测:在sendfile 完成后尝试关闭fd。在接收者完成之前,您是否在发送者中保持套接字打开?可能是发送者终止套接字的速度太快了。 不会是原因,但您不应该在发送者中因发送的字节数而增加offset 吗? @cdarke,我已经尝试了这两种方法,发送后关闭或不关闭套接字。如果我关闭它,recv() 在显示消息后过早终止,如果我在发送方中打开套接字,recv() 会继续阻塞,期待更多数据 @TripeHound,是的,我纠正了这一点,谢谢你的化妆品 :) @tripeHound: sendfile() 应该在退出时增加 offset。请参阅documentation:“如果 offset 不为 NULL,则它指向一个保存文件偏移量的变量,sendfile() 将从该文件偏移量开始从 in_fd 读取数据。当 sendfile() 返回时,此变量将设置为读取的最后一个字节之后的字节偏移量。 如果 offset 不为 NULL,则 sendfile() 不会修改 in_fd 的当前文件偏移量;否则调整当前文件偏移量以反映从 in_fd 读取的字节数。" 【参考方案1】:

假设 remain_data 是实际文件大小,那么您的两个循环都是错误的。它们应该更像这样:

while (remain_data > 0)

    len = recv(welcomeSocket, buffer, min(remain_data, BUFSIZ), 0);
    if (len <= 0) 
        // error handling...
        break;
    
    fwrite(buffer, sizeof(char), len, received_file);
    remain_data -= len;
    fprintf(stdout, "Receive %zd bytes and we hope :- %d bytes\n", len, remain_data);

off_t offset = 0;
while (remain_data > 0)

    sent_bytes = sendfile(fds[i].fd, fd, &offset, min(remain_data, BUFSIZ));
    if (sent_bytes <= 0) 
        // error handling...
        break;
    
    fprintf(stdout, "Server sent %u bytes from file's data, offset is now : %jd \n", sent_bytes, (intmax_t)offset);
    remain_data -= sent_bytes;
    fprintf(stdout, "remaining data = %d\n", remain_data);

【讨论】:

谢谢雷米,你正确地指出了我的错误,现在就像一个魅力:)

以上是关于本地主机上的 recv() 数据丢失的主要内容,如果未能解决你的问题,请参考以下文章

本地主机上丢失的执行程序驱动程序:执行程序心跳超时

Rails - 在本地主机上创建内部服务器错误(500)

即使对于“pktcount * pktsize”< SO_RCVBUF,linux socket recv 缓冲区数据包也会丢失

PostgreSQL(丢失数据的复制或复制)-远程主PostgreSQL的只读权限

autoload.php 在那里时丢失

falcon 数据丢失处理方法参考