liunx下高效率UDP/TCP发送RTP包

前言:发送RTP码流时,通常需要将视频数据切分成多个MTU内大小的块再使用socket发出去。如果是每次调用send函数只发送一个RTP包,send函数调用会很频繁从而导致性能下降。这时需要使用sendmsg 和 sendmmsg函数批量发送多个RTP达到优化效果。

 

sendmsg : 对于发送RTP包,sendmsg只能用在TCP发送场景,如果UDP也使用将导致所有RTP包被当成一个UDP包发出,见代码1。

 

sendmmsg: 可以一次发送多个RTP包,且每个RTP包使用一个UDP包封装。两个函数都可以向sendto那样无链接发送,需要在struct msghdr结构体中将msg_name和msg_namelen填sendto最好两个参数即可。创建连接效率会更高,见代码2。

 

代码1:

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/times.h>

#define MAX_SEG 20
#define SEG_SIZE 1500 
#define PKG_NUM  10000*100


int 
main(void) 
{
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        struct sockaddr_in server_addr;
        bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(28000);
        inet_pton(AF_INET, "192.168.21.173", &server_addr.sin_addr.s_addr);
        if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) 
        {
                printf("connect error!\n");
                return -1;
        }


        char data[SEG_SIZE];
        memset(data, 0xfe, sizeof(data));

        struct iovec iovs[MAX_SEG];
        memset(iovs, 0, sizeof(iovs));

        int i;
        for (i = 0; i < MAX_SEG; ++i) 
        {
                iovs[i].iov_base = data;
                iovs[i].iov_len = sizeof(data);
        }

        struct msghdr msg_hdr;
        memset(&msg_hdr, 0, sizeof(msg_hdr));
        msg_hdr.msg_iov = iovs;
        msg_hdr.msg_iovlen = MAX_SEG;


        time_t start = times(0);
        unsigned int send_num = 0;
        while (1)//send_num < PKG_NUM)
        {
                if(0 > sendmsg(sockfd, &msg_hdr, 0))
                {
                        printf("sendmmsg error\n");
                        //break;
                }
                send_num += MAX_SEG;
        }

        printf("use time:%u0ms\n", times(0)-start);
        close(sockfd);
        return 0;
}

 

代码2:

//#define _GNU_SOURCE
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/times.h>
#include <iostream>

#define MAX_SEG 20
#define SEG_SIZE 1500
#define PKG_NUM  10000*100

/*
struct mmsghdr
{
        struct msghdr msg_hdr;
        unsigned int msg_len;
};
*/

int
main(void)
{
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        struct sockaddr_in server_addr;
        bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(28000);
        inet_pton(AF_INET, "192.168.21.173", &server_addr.sin_addr.s_addr);
        if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
        {
                printf("connect error!\n");
                return -1;
        }


        struct iovec iovs[MAX_SEG];
        struct mmsghdr mmsg[MAX_SEG];
        bzero(&iovs, sizeof(iovs));
        bzero(&mmsg, sizeof(mmsg));
        char data[SEG_SIZE];
        memset(data, 0xfe, sizeof(data));

        int i;
        for (i = 0; i < MAX_SEG; ++i)
        {
                iovs[i].iov_base = data;
                iovs[i].iov_len = sizeof(data);

                mmsg[i].msg_hdr.msg_iov = iovs + i;
                mmsg[i].msg_hdr.msg_iovlen = 1;
        }

        time_t start = times(0);
        unsigned int send_num = 0;
        while (1)//send_num < PKG_NUM)
        {

                 if(0 > sendmmsg(sockfd, mmsg, MAX_SEG, 0))
                {
                        printf("sendmmsg error\n");
                        //break;
                }
                send_num += MAX_SEG;
        }

        printf("use time:%u0ms\n", times(0)-start);
        close(sockfd);
        return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值