当前位置:  开发笔记 > 程序员 > 正文

连续调用recvfrom()会丢失数据?

如何解决《连续调用recvfrom()会丢失数据?》经验,为你挑选了1个好方法。

我正在开发一个使用UDP的可靠文件传输程序.(用于计算机网络课程.)

我的问题是 - 好吧,考虑这种情况:

    发送者(例如)要发送12个字节的数据.所以发件人执行此调用:

    sendto(fd, &buf, 12, 0, (struct sockaddr *)&cliaddr,sizeof(cliaddr));
    

    这以不可靠的方式发送12个字节的数据.该数据的前4个字节恰好是"消息长度"字段.在这种情况下,前4个字节的值可能为0x0000000C

    接收器想要使用recvfrom()读取前4个字节.看到段大小是12个字节,它想要读取剩余的8个字节.所以接收器可能看起来像这样:

    /* read the segment size */
    recvfrom(sockfd,&buf,4,0,(struct sockaddr *)&cliaddr,&len);
    
    /* do some arithmetic, use bzero(), etc */
    
    /* read the rest of the data */
    recvfrom(sockfd,&buf,8,0,(struct sockaddr *)&cliaddr,&len);
    

当我执行此代码时,我可以毫无问题地收到前4个字节.但是当我尝试获取剩余数据时,这些数据似乎丢失了.在我的输出中,我得到了垃圾 - 它看起来像发送者发送到()的接下来的 12个字节的一部分.

这是预期的行为吗?也就是说,如果单个recvfrom()调用没有读取所有已发送的数据,是否可以保证该数据(剩余的8个字节)可供我使用?

似乎发送段头(包括其大小)的标准方法(后跟有效负载)不起作用.这是否意味着我需要发送2个单独的段 - 一个只包含头信息,然后是第二个带有效载荷的段?或者我只是错误地使用这些系统调用(或者是否存在我缺少的标志或setsockopt()?)



1> camh..:

从recv(2)手册页:

如果消息太长而无法容纳在提供的缓冲区中,则可能会丢弃多余的字节,具体取决于接收消息的套接字类型.

这就像发生在你身上的样子.

您应该有一个最大邮件大小的缓冲区并读取该数量.您将只读取一个数据报,并返回长度.然后,您可以从缓冲区的前面解析长度,并根据返回的recvfrom(2)进行验证.


由于您正在设计此协议,因此请随意选择最大尺寸.UNP Vol1,3rd Edition建议使用比您期望接收的最大消息大一个字节的缓冲区.如果recvfrom()返回的值等于缓冲区的长度,则应将其视为错误.
推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有