最近调试媒体服务器,发现被叫的媒体流总是抖动的厉害,不清楚是网络原因还是媒体服务器的代码问题。
为了方便排查问题,我编写了一个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