• UDP传输rtp数据包丢帧


    udp丢包情况:
    1.连续发送数据包太快 (每发一包数据usleep(40));
    2.发送数据包太长 (数据进行切割成1400byte发送);
    3.接收端处理时间过长导致丢包:调用recv方法接收端收到数据 后,处理数据花了一些时间,处理完后再次调用recv方法,
    在这二次调用间隔里,发过来的包可能丢失。对于这种情况可以修改接收端,将包接收后存入一个缓冲区,然后迅速返回继续recv。
    4.发送的包较大,超过接受者缓存导致丢包:包超过mtu size数倍,几个大的udp包可能会超过接收者的缓冲,导致丢包。
    这种情况可以设置socket接收缓冲。以前遇到过这种问题,我把接收缓冲设置成64K就解决了。

    Socket缓冲区大小修改与系统设置:(每个Socket在Linux中都映射为一个文件,并与内核中两个缓冲区(读缓冲区、写缓冲区)相关联。或者说,每个Socket拥有两个内核缓冲区。有时,我们需要修改缓冲区的内核限制的最大值,使其符合我们的实际需求)
    cat /proc/sys/net/core/rmem_max 212992
    rmem_max:一个Socket的读缓冲区可由程序设置的最大值,单位字节;
    wmem_max:一个Socket的写缓冲区可由程序设置的最大值,单位字节;
    rmem_default:一个Socket的被创建出来时,默认的读缓冲区大小,单位字节;
    wmem_default:一个Socket的被创建出来时,默认的写缓冲区大小,单位字节;

    应用程序级修改缓冲区大小
    我们可以在程序中动态地修改(通过setsockopt系统调用)持有的有效Socket的读写缓冲区大小。
    
    复制代码
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    
    int main(int argc, char **argv)
    {
         if (argc != 2)
         {
             printf("Usage: %s $RCFBUFSIZE
    ", argv[0]);
             goto error;
         }
    
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
         if (sockfd < 0)
         {
             printf("create socket error=%d(%s)!!!
    ", errno, strerror(errno));
             goto error;
         }
    
        // 查看系统默认的socket接收缓冲区大小
         int defRcvBufSize = -1;
         socklen_t optlen = sizeof(defRcvBufSize);
         if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &defRcvBufSize, &optlen) < 0)
         {
             printf("getsockopt error=%d(%s)!!!
    ", errno, strerror(errno));
             goto error;
         }
         printf("OS default udp socket recv buff size is: %d
    ", defRcvBufSize);
    
        // 按照执行参数设置UDP SOCKET接收缓冲区大小
         int rcvBufSize = atoi(argv[1]);
         if (rcvBufSize <= 0)
         {
             printf("rcvBufSize(%d) <= 0, error!!!
    ", rcvBufSize);
             goto error;
         }
         printf("you want to set udp socket recv buff size to %d
    ", rcvBufSize);
         optlen = sizeof(rcvBufSize);
         if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, optlen) < 0)
         {
             printf("setsockopt error=%d(%s)!!!
    ", errno, strerror(errno));
             goto error;
         }
         printf("set udp socket(%d) recv buff size to %d OK!!!
    ", sockfd, rcvBufSize);
    
        // 查看当前UDP SOCKET接收缓冲区大小
         int curRcvBufSize = -1;
         optlen = sizeof(curRcvBufSize);
         if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &curRcvBufSize, &optlen) < 0)
         {
             printf("getsockopt error=%d(%s)!!!
    ", errno, strerror(errno));
             goto error;
         }
         printf("OS current udp socket(%d) recv buff size is: %d
    ", curRcvBufSize);
    
        close(sockfd);
    
        exit(0);
    
    error:
         if (sockfd >= 0)
             close(sockfd);
         exit(1);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
  • 相关阅读:
    linux 使用 squid
    (c语言进阶)数据存储——浮点型存储
    qizhidao参数分析
    【自学笔记】Python中的逻辑函数:any()、all()及同类函数的用法与示例
    摄像头webrtc对讲方案之metaRTC+ZLMediaKit
    爱尔兰公司改名要遵循一定的程序和规定
    04_瑞萨GUI(LVGL)移植实战教程之驱动LCD屏(SPI)
    指令手册术语缩写
    154_一键批量建立时间智能度量值
    torchvision.datasets.ImageFolder前的数据整理及使用方法
  • 原文地址:https://blog.csdn.net/xt18971492243/article/details/125491208