LINUX编程实战指发送UDP消息

简介: LINUX编程实战指发送UDP消息

最近调试媒体服务器,发现被叫的媒体流总是抖动的厉害,不清楚是网络原因还是媒体服务器的代码问题。


为了方便排查问题,我编写了一个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


相关文章
|
3月前
|
Shell Linux
Linux shell编程学习笔记30:打造彩色的选项菜单
Linux shell编程学习笔记30:打造彩色的选项菜单
|
29天前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
2月前
|
网络协议 Linux 网络性能优化
Linux C/C++之TCP / UDP通信
这篇文章详细介绍了Linux下C/C++语言实现TCP和UDP通信的方法,包括网络基础、通信模型、编程示例以及TCP和UDP的优缺点比较。
38 0
Linux C/C++之TCP / UDP通信
|
2月前
|
网络协议 Linux 网络性能优化
Linux基础-socket详解、TCP/UDP
综上所述,Linux下的Socket编程是网络通信的重要组成部分,通过灵活运用TCP和UDP协议,开发者能够构建出满足不同需求的网络应用程序。掌握这些基础知识,是进行更复杂网络编程任务的基石。
124 1
|
3月前
|
Shell Linux
Linux shell编程学习笔记82:w命令——一览无余
Linux shell编程学习笔记82:w命令——一览无余
|
3月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
114 6
|
3月前
|
监控 Linux Shell
30 个实用的 Linux 命令贴与技巧,提升你的效率(附实战案例)
本文介绍了30个实用的Linux命令及其应用场景,帮助你提升命令行操作效率。涵盖返回目录、重新执行命令、查看磁盘使用情况、查找文件、进程管理、网络状态监控、定时任务设置等功能,适合各水平的Linux用户学习和参考。
|
3月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
146 3
|
3月前
|
Shell Linux Python
python执行linux系统命令的几种方法(python3经典编程案例)
文章介绍了多种使用Python执行Linux系统命令的方法,包括使用os模块的不同函数以及subprocess模块来调用shell命令并处理其输出。
48 0
|
4月前
|
项目管理 敏捷开发 开发框架
敏捷与瀑布的对决:解析Xamarin项目管理中如何运用敏捷方法提升开发效率并应对市场变化
【8月更文挑战第31天】在数字化时代,项目管理对软件开发至关重要,尤其是在跨平台框架 Xamarin 中。本文《Xamarin 项目管理:敏捷方法的应用》通过对比传统瀑布方法与敏捷方法,揭示敏捷在 Xamarin 项目中的优势。瀑布方法按线性顺序推进,适用于需求固定的小型项目;而敏捷方法如 Scrum 则强调迭代和增量开发,更适合需求多变、竞争激烈的环境。通过详细分析两种方法在 Xamarin 项目中的实际应用,本文展示了敏捷方法如何提高灵活性、适应性和开发效率,使其成为 Xamarin 项目成功的利器。
53 1