最近调试媒体服务器,发现被叫的媒体流总是抖动的厉害,不清楚是网络原因还是媒体服务器的代码问题。
为了方便排查问题,我编写了一个UDP发送的小工具。根据传入目的地的IP、PORT和发送的时长。该工具就可以按照20ms的间隔进行重复发送RTP流。
编程思路:
首先初始化本端udp的socket套接字:
memset(buf,1,sizeof(buf)); char * desip = argv[1]; int destport = atoi(argv[2]); int sec = atoi(argv[3]); int count = sec * 1000 / 20; int fd=-1; fd=socket(AF_INET,SOCK_DGRAM,0); fcntl(fd,F_SETFL,O_NDELAY); int reuse_addr_flag=1; int success=setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&reuse_addr_flag,sizeof(reuse_addr_flag)); if(success<0) { perror("udp setsockopt(SO_REUSEADDR): "); close(fd); return 0; } int sendBufSize,sendBufLength; sendBufSize=4*1024*1024; sendBufLength=sizeof sendBufSize; if(setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(char*)&sendBufSize,sendBufLength)<0) { perror("udp setsockopt(SO_SNDBUF): "); return 0; } if(setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(char*)&sendBufSize,sendBufLength)<0) { perror("udp setsockopt(SO_RCVBUF): "); return 0; } struct sockaddr_in localaddr; in_addr_t net_addr=inet_addr("0.0.0.0"); //ntohl(l_ipv4.ip_dw) memset(&localaddr,0,sizeof(struct sockaddr_in)); localaddr.sin_family = AF_INET; localaddr.sin_port = 30008; memcpy((struct sockaddr*)&localaddr.sin_addr,(void *)(&net_addr),sizeof(net_addr)); if (bind(fd,(struct sockaddr *)&localaddr,sizeof(struct sockaddr_in)) != 0) { return 0; }
根据目的端的IP、PORT设置套接字:
int success; struct sockaddr *pDestAddr = NULL; struct sockaddr_in destAddr; int len; memset(&destAddr,0,sizeof(struct sockaddr_in)); in_addr_t net_addr=inet_addr(host); destAddr.sin_family = AF_INET; destAddr.sin_port = htons(port); memcpy((struct sockaddr*)&destAddr.sin_addr,(void *)(&net_addr),sizeof(net_addr)); pDestAddr = (struct sockaddr*)&destAddr; len = sizeof(destAddr);
最后调用sendto函数,发送UDP数据
success = sendto(fd,buffer,length,0, pDestAddr, len); if(success<0) { char *buf = new char[length + 128]; sprintf(buf, "sendto(%d, %s, %d, %s, %d):", fd, buffer, length, host, port); perror(buf); delete []buf; }
完整的代码如下:
#include <errno.h> #include <fcntl.h> #include <netdb.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <strings.h> #include <signal.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/wait.h> #include <time.h> #include <sys/time.h> #include <unistd.h> void sendUDPMsg(int fd,char* host,unsigned short port,char* buffer,int length); int main(int argc,char* argv[]) { char buf[640]={1}; memset(buf,1,sizeof(buf)); char * desip = argv[1]; int destport = atoi(argv[2]); int sec = atoi(argv[3]); int count = sec * 1000 / 20; int fd=-1; fd=socket(AF_INET,SOCK_DGRAM,0); fcntl(fd,F_SETFL,O_NDELAY); int reuse_addr_flag=1; int success=setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&reuse_addr_flag,sizeof(reuse_addr_flag)); if(success<0) { perror("udp setsockopt(SO_REUSEADDR): "); close(fd); return 0; } int sendBufSize,sendBufLength; sendBufSize=4*1024*1024; sendBufLength=sizeof sendBufSize; if(setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(char*)&sendBufSize,sendBufLength)<0) { perror("udp setsockopt(SO_SNDBUF): "); return 0; } if(setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(char*)&sendBufSize,sendBufLength)<0) { perror("udp setsockopt(SO_RCVBUF): "); return 0; } struct sockaddr_in localaddr; in_addr_t net_addr=inet_addr("0.0.0.0"); //ntohl(l_ipv4.ip_dw) memset(&localaddr,0,sizeof(struct sockaddr_in)); localaddr.sin_family = AF_INET; localaddr.sin_port = 30008; memcpy((struct sockaddr*)&localaddr.sin_addr,(void *)(&net_addr),sizeof(net_addr)); if (bind(fd,(struct sockaddr *)&localaddr,sizeof(struct sockaddr_in)) != 0) { return 0; } int i =0; for(i=0;i<count;i++) { sendUDPMsg(fd,desip,destport,buf,sizeof(buf)); usleep(1000 * 20); } return 1; } void sendUDPMsg(int fd,char* host,unsigned short port,char* buffer,int length) { int success; struct sockaddr *pDestAddr = NULL; struct sockaddr_in destAddr; int len; memset(&destAddr,0,sizeof(struct sockaddr_in)); in_addr_t net_addr=inet_addr(host); destAddr.sin_family = AF_INET; destAddr.sin_port = htons(port); memcpy((struct sockaddr*)&destAddr.sin_addr,(void *)(&net_addr),sizeof(net_addr)); pDestAddr = (struct sockaddr*)&destAddr; len = sizeof(destAddr); success = sendto(fd,buffer,length,0, pDestAddr, len); if(success<0) { char *buf = new char[length + 128]; sprintf(buf, "sendto(%d, %s, %d, %s, %d):", fd, buffer, length, host, port); perror(buf); delete []buf; } }
代码编译方法如下:
g++ -g testrtpudp.c -o testrtp
使用方法如下:
./testrtp 192.168.2.77 3950 1