C UDP组播接收丢包

Posted

技术标签:

【中文标题】C UDP组播接收丢包【英文标题】:C UDP Multicast receive packet lost 【发布时间】:2015-01-22 05:36:10 【问题描述】:

我编写了一个 C 程序来接收 UDP 多播数据包,它可以工作。但是,当程序运行几秒钟后,丢包的情况就经常发生。当我按 Ctrl + C 终止程序并重新启动它时,它将接收大部分数据包,但几秒钟后会发生数据包丢失。这很奇怪,有什么问题吗?这是我的 C 代码。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>

#include <fcntl.h>
#include <sys/ioctl.h>
#include <android/log.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>

#define BUF_SIZE 4

int mjpeg_main()
    int sockfd;
    struct sockaddr_in localSock;
    struct ip_mreq group;
    char buf[BUF_SIZE];
    int len = sizeof(localSock);

/* Create a datagram socket on which to receive. */
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)

    perror("Can't create socket!");
    exit(1);


/* Enable SO_REUSEADDR to allow multiple instances of this */
/* application to receive copies of the multicast datagrams. */
int reuse = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)

    perror("Setting SO_REUSEADDR error");
    close(sockfd);
    exit(1);


int n = 1024 * 1024;
if (setsockopt(sockfd,SOL_SOCKET,SO_RCVBUFFORCE,(const char*)&n, sizeof(int)) == -1)

  // deal with failure, or ignore if you can live with the default size




/* Bind to the proper port number with the IP address */
/* specified as INADDR_ANY. */
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(2068);
localSock.sin_addr.s_addr = INADDR_ANY;
if(bind(sockfd, (struct sockaddr*)&localSock, sizeof(localSock)))

    perror("Binding datagram socket error");
    close(sockfd);
    exit(1);


/* Join the multicast group 239.100.15.101 on the local 203.106.93.94 */
/* interface. Note that this IP_ADD_MEMBERSHIP option must be */
/* called for each local interface over which the multicast */
/* datagrams are to be received. */
group.imr_multiaddr.s_addr = inet_addr("239.100.15.101");
group.imr_interface.s_addr = inet_addr("10.100.15.115");
if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)

    perror("Adding multicast group error");
    close(sockfd);
    exit(1);



printf("Start to receive!n");
__android_log_print(ANDROID_LOG_INFO,"mjpeg","mjpeg start !!");

//Wait for connect
while(1)

    memset(buf, 0, sizeof(buf));
    int z = recvfrom(sockfd,                      // Socket
                     buf,                         // Receiving buffer
                     sizeof buf,                  // Max recv buf size
                     0,                           // Flags: no options
                     (struct sockaddr *)&localSock,// Addr
                     &len);                       // Addr len, in & out
    if ( z < 0 ) 
    
        perror("recv");
        exit(1);
    

    printf("Frame: %02X:%02X, Sequence: %02X:%02X\n", buf[0], buf[1], buf[2], buf[3]);


close(sockfd);
return 0;

而且,这就是结果。发送者是一个硬件,一个帧包含许多序列。序号会依次增加。

帧:09:1F,序列:00:00 帧:09:1F,序列:00:01 帧:09:1F,序列:00:02 帧:09:1F,序列:00:03 帧:09:1F,序列:00:04 帧:09:1F,序列:00:05 帧:09:1F,序列:00:06 帧:09:1F,序列:00:07 帧:09:1F,序列:00:08 帧:09:1F,序列:00:09 帧:09:1F,序列:00:0A 帧:09:1F,序列:00:0B 帧:09:1F,序列:00:0C 帧:09:1F,序列:00:0D 帧:09:1F,序列:00:0E 帧:09:1F,序列:00:0F 帧:09:1F,序列:00:10 帧:09:1F,序列:00:11 帧:09:1F,序列:00:12 帧:09:1F,序列:00:13 帧:09:1F,序列:00:14 帧:09:1F,序列:00:15 帧:09:1F,序列:00:16 帧:09:1F,序列:00:17 帧:09:1F,序列:00:18 帧:09:1F,序列:00:19 帧:09:1F,序列:00:1A 帧:09:1F,序列:00:1B 帧:09:1F,序列:00:1C 帧:09:1F,序列:00:1D 帧:09:1F,序列:00:1E 帧:09:1F,序列:00:1F 帧:09:1F,序列:00:20 帧:09:1F,序列:00:21 帧:09:1F,序列:00:22 帧:09:1F,序列:00:23 帧:09:1F,序列:00:24 帧:09:1F,序列:00:25 帧:09:1F,序列:00:26 帧:09:1F,序列:00:27 帧:09:1F,序列:00:28 帧:09:1F,序列:00:29 帧:09:1F,序列:00:2A 帧:09:1F,序列:00:2B 帧:09:1F,序列:00:2C 帧:09:1F,序列:00:2D 帧:09:1F,序列:00:2E 帧:09:1F,序列:00:2F 帧:09:1F,序列:00:30 帧:09:1F,序列:00:31 帧:09:1F,序列:00:32 帧:09:1F,序列:00:33 帧:09:1F,序列:00:34 帧:09:1F,序列:00:35 帧:09:1F,序列:00:36 帧:09:1F,序列:00:37 帧:09:1F,序列:00:38 帧:09:1F,序列:00:39 帧:09:1F,序列:00:3A 帧:09:1F,序列:00:3B 帧:09:1F,序列:00:3C 帧:09:1F,序列:00:3D 帧:09:1F,序列:00:3E 帧:09:1F,序列:00:3F 帧:09:1F,序列:00:40 帧:09:1F,序列:00:41 帧:09:1F,序列:00:42 帧:09:1F,序列:00:43 帧:09:1F,序列:00:44 帧:09:1F,序列:00:45 帧:09:1F,序列:00:46 帧:09:1F,序列:00:47 帧:09:1F,序列:00:48 帧:09:1F,序列:00:49 帧:09:1F,序列:00:4A 帧:09:1F,序列:00:4B 帧:09:1F,序列:00:4C 帧:09:1F,序列:00:4D 帧:09:1F,序列:80:4E 帧:09:20,序列:00:00 帧:09:20,序列:00:01 帧:09:20,序列:00:02 帧:09:20,序列:00:03 帧:09:20,序列:00:04 帧:09:20,序列:00:05 帧:09:20,序列:00:06 帧:09:20,序列:00:07 帧:09:20,序列:00:08 帧:09:20,序列:00:09 帧:09:20,序列:00:0A 帧:09:20,序列:00:0B 帧:09:20,序列:00:0C 帧:09:20,序列:00:0D 帧:09:20,序列:00:0E 帧:09:20,序列:00:0F 帧:09:20,序列:00:10 帧:09:20,序列:00:11 帧:09:20,序列:00:12 帧:09:20,序列:00:13 帧:09:20,序列:00:14 帧:09:20,序列:00:15 帧:09:20,序列:00:16 帧:09:20,序列:00:17 帧:09:20,序列:00:18 帧:09:20,序列:00:19 帧:09:20,序列:00:1A 帧:09:20,序列:00:1B 帧:09:20,序列:00:1C 帧:09:20,序列:00:1D 帧:09:20,序列:00:1E 帧:09:20,序列:00:1F 帧:09:20,序列:00:20 帧:09:20,序列:00:21 帧:09:20,序列:00:22 帧:09:20,序列:00:23 帧:09:20,序列:00:24 帧:09:20,序列:00:25 帧:09:20,序列:00:26 帧:09:20,序列:00:27 帧:09:20,序列:00:28 帧:09:20,序列:00:29 帧:09:20,序列:00:2E 帧:09:20,序列:00:31 帧:09:20,序列:00:37 帧:09:20,序列:00:3B 帧:09:20,序列:00:3D 帧:09:20,序列:00:3F 帧:09:20,序列:00:41 帧:09:20,序列:00:42 帧:09:20,序列:00:44 帧:09:20,序列:00:46 帧:09:20,序列:00:4B 帧:09:20,序列:80:4E 帧:09:21,序列:00:00 帧:09:21,序列:00:01 开始丢包... 帧:09:21,序列:00:06 帧:09:21,序列:00:10 帧:09:21,序列:00:1C 帧:09:21,序列:00:25 帧:09:21,序列:00:2F 帧:09:21,序列:00:35 帧:09:21,序列:00:3B 帧:09:21,序列:00:3C 帧:09:21,序列:00:3E 帧:09:21,序列:00:40 帧:09:21,序列:00:42 帧:09:21,序列:00:43 帧:09:21,序列:00:45 帧:09:21,序列:00:47 帧:09:21,序列:00:4D 帧:09:22,序列:00:01 帧:09:22,序列:00:05 帧:09:22,序列:00:0D 帧:09:22,序列:00:1B 帧:09:22,序列:00:23 帧:09:22,序列:00:2F 帧:09:22,序列:00:34 帧:09:22,序列:00:3A 帧:09:22,序列:00:3C 帧:09:22,序列:00:3E 帧:09:22,序列:00:40 帧:09:22,序列:00:41 帧:09:22,序列:00:43 帧:09:22,序列:00:45 帧:09:22,序列:00:47 帧:09:22,序列:00:4D 帧:09:23,序列:00:01 帧:09:23,序列:00:04 帧:09:23,序列:00:0A 帧:09:23,序列:00:19 帧:09:23,序列:00:20 帧:09:23,序列:00:2E 帧:09:23,序列:00:32 帧:09:23,序列:00:39 帧:09:23,序列:00:3C 帧:09:23,序列:00:3E 帧:09:23,序列:00:3F 帧:09:23,序列:00:41 帧:09:23,序列:00:43 帧:09:23,序列:00:45 帧:09:23,序列:00:46 帧:09:23,序列:00:4D

【问题讨论】:

为什么不应该发生? UDP 是一个不可靠的协议,或者说它缺乏可靠性特性。 是的,我知道,有什么办法可以减少这种情况吗?现在丢包的程度太严重了。 除了使用不太繁忙的网络或只是加快网络速度之外,您无能为力。例如,您不需要memset() 调用。当然,您会通过打印来减慢速度。 尝试谷歌搜索“网络拥塞”问题。您可以尝试以较慢的速度发送数据包。 @Marian 不是。 '发件人是硬件'。 【参考方案1】:

问题解决了。原因是我们的PHY使用了外部晶振,内核的时钟配置不正确。

【讨论】:

以上是关于C UDP组播接收丢包的主要内容,如果未能解决你的问题,请参考以下文章

android-Android udp接收不到组播,请问如何解决

RT1052接收不到 UDP 组播包 问题解决

如何接收组播 UDP?

Android对UDP组播接收数据的有限支持

求助 有个android手机建立热点后发送组播信息的问题

sendto频率过快导致发送丢包