基于RTP协议的数据通讯程序

最近调试jrtplib的示例程序example1,屡调不通, 在一筹莫展之际,突然想起,会不会是ip地址从字符串向长整形转化的时候存在问题 呢。给destip强制写入一个 7f000001 (就是本机回环测试ip:127.0.0.1),再调试,果然通过。嗨,没想到真是这里出了问题。现在把代码贴出来,这里贴的代码经过了一些改动,可以用 了,而且研究了packet类的各个成员,以及如何获取打包后的数据及包头的方法(每包的包头是12字节)。另外,我的jrtplib编译成了无线程版 本,本文给出的两个例子也都是针对无线程支持的jrtplib。初开始,我把jrtplib编译成为有线程版本,结果发现总是有问题,就干脆把线程支持部 分去掉了。

example1 程序如下:

----------------------------------------------------------------------------------------------------------------------------------

/*
   Here's a small IPv4 example: it asks for a portbase and a destination and
   starts sending packets to that destination.
   这是一个小小的IPv4的示例程序:它请求一个起始端口和一个目标地址然后开始发送
   一些包到那个目标地址。
*/

#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#ifndef WIN32
 #include <netinet/in.h>
 #include <arpa/inet.h>
#else
 #include <winsock2.h>
#endif // WIN32
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>


#pragma comment(lib, "jrtplib.lib")
#pragma comment(lib, "Ws2_32.lib")

//
// This function checks if there was a RTP error. If so, it displays an error
// message and exists.
// 这个函数检测是否有一个RTP错误,如果有,它显示一个错误消息,并且退出
//(原注释中怀疑是写错了,应为exits.)
//
void checkerror(int rtperr)
{
 if (rtperr < 0)
 {
  std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
  getchar();
  exit(-1);
 }
}

uint32_t str_ip_to_long_ip(char *strip)
{
 int i,j=3;
 unsigned char byt[4];
 long lret;

 for ( i=0 ; i < strlen ( strip ) ; i++ )
 {
  
 }
 return lret;
}

//
// The main routine
// 主例程

int main(void)
{
#ifdef WIN32
 WSADATA dat;
 //makeword(lobyte,hibyte)把两个字节连成一个字
 WSAStartup(MAKEWORD(2,2),&dat);  
#endif // WIN32
 
 RTPSession sess;
 uint16_t portbase,destport;
 uint32_t destip;
 std::string ipstr;
 int status,i,num;

    // First, we'll ask for the necessary information
 //首先,我们需要获得必要的信息。  
 std::cout << "Enter local portbase(请输入本地起始端口):" << std::endl;
 std::cin >> portbase;
 std::cout << std::endl;
 
 std::cout << "Enter the destination IP address(请输入目标IP地址)" << std::endl;
 std::cin >> ipstr;
 destip = inet_addr(ipstr.c_str());//把字符串转成32位的IP地址
 if (destip == INADDR_NONE)
 {
  std::cerr << "Bad IP address specified(指定了错误的IP地址)" << std::endl;
  return -1;
 }
 
 // The inet_addr function returns a value in network byte order, but
 // we need the IP address in host byte order, so we use a call to
 // ntohl
 // inet_addr函数返回一个以网络字节序的值,但是我们需要的是主字节序的值,
 // 所以我们需要使用一个ntohl的调用。
 destip = ntohl(destip);  //n (network byte order) to h (host byte order)
 //l (long)
 
 //调试 
 destip=0x7f000001;

 std::cout << "Enter the destination port(请输入目标端口)" << std::endl;
 std::cin >> destport;
 
 std::cout << std::endl;
 std::cout << "Number of packets you wish to be sent(你希望发送的包的个数):" << std::endl;
 std::cin >> num;
 
 // Now, we'll create a RTP session, set the destination, send some
 // packets and poll for incoming data.
 // 现在,我们可以创建一个rtp会话,设置目标,发送一些包,然后轮询流入的数据。

 RTPUDPv4TransmissionParams transparams;
 RTPSessionParams sessparams;
 
 // IMPORTANT: The local timestamp unit MUST be set, otherwise
 //            RTCP Sender Report info will be calculated wrong
 // In this case, we'll be sending 10 samples each second, so we'll
 // put the timestamp unit to (1.0/10.0)
 // 重要:本地时间戳单元必须设置,否则在这种情况下RTCP发送者报告信息将会被计算错误,
 //我们将会每秒发送10个样本,所以我们把时间戳单元里面放上(1.0 / 10.0)。

 sessparams.SetOwnTimestampUnit(1.0/10.0);  
 
 sessparams.SetAcceptOwnPackets(true);
 transparams.SetPortbase(portbase);
 status = sess.Create(sessparams,&transparams);   //创建会话
 checkerror(status);
 
 RTPIPv4Address addr(destip,destport);
 
 status = sess.AddDestination(addr);               //添加目标ip地址
 checkerror(status);
 
 for (i = 1 ; i <= num ; i++)
 {
  printf("\nSending packet %d/%d/%s \n",i,num,"1234567890");
  
  // send the packet   发送数据包
  status = sess.SendPacket((void *)"1234567890",10,0,false,10);
  checkerror(status);
  
  sess.BeginDataAccess(); //开始数据访问
  
  // check incoming packets  检查流入的包
  if (sess.GotoFirstSourceWithData())
  {
   do
   {
    RTPPacket *pack;
    
    while ((pack = sess.GetNextPacket()) != NULL)
    {
     // You can examine the data here    你可以在这检查数据
     printf("Got packet !\n");
     
     // we don't longer need the packet, so
     // we'll delete it 我们不再需要这个包,所以我们删除它
     delete pack;
    }
   } while (sess.GotoNextSourceWithData());
  }
  
  sess.EndDataAccess();  //结束数据访问;

#ifndef RTP_SUPPORT_THREAD
  status = sess.Poll();
  checkerror(status);
#endif // RTP_SUPPORT_THREAD
  
  RTPTime::Wait(RTPTime(1,0));
 }
 
 sess.BYEDestroy(RTPTime(10,0),0,0);

#ifdef WIN32
 WSACleanup();
#endif // WIN32

 getchar();
 return 0;
}

 

----------------------------------------------------------------------------------------------------------------------------------

example3 程序如下:

----------------------------------------------------------------------------------------------------------------------------------

/*
   This IPv4 example listens for incoming packets
   and automatically adds destinations
   for new sources.
   这个ipv4示例程序监听流入的数据并且自动的为新的源添加目标地址
*/

#include "rtpsession.h"
#include "rtppacket.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#ifndef WIN32
 #include <netinet/in.h>
 #include <arpa/inet.h>
#else
 #include <winsock2.h>
#endif // WIN32
#include "rtpsourcedata.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

#pragma comment (lib,"Ws2_32.lib")

//
// This function checks if there was a RTP error. If so, it displays an error
// message and exists.
//

void checkerror(int rtperr)
{
 if (rtperr < 0)
 {
  std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
  getchar();
  exit(-1);
 }
}

//
// The new class routine
// 新的类例程;继承自RTPSession类

class MyRTPSession : public RTPSession
{
protected:
 void OnNewSource(RTPSourceData *dat)
 {
  if (dat->IsOwnSSRC())
   return;

  uint32_t ip;
  uint16_t port;
  
  if (dat->GetRTPDataAddress() != 0)
  {
   const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());
   ip = addr->GetIP();
   port = addr->GetPort();
  }
  else if (dat->GetRTCPDataAddress() != 0)
  {
   const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());
   ip = addr->GetIP();
   port = addr->GetPort()-1;
  }
  else
   return;
  
  RTPIPv4Address dest(ip,port);
  AddDestination(dest);

  struct in_addr inaddr;
  inaddr.s_addr = htonl(ip);
  std::cout << "Adding destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl;
 }

 void OnBYEPacket(RTPSourceData *dat)
 {
  if (dat->IsOwnSSRC())
   return;
  
  uint32_t ip;
  uint16_t port;
  
  if (dat->GetRTPDataAddress() != 0)
  {
   const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());
   ip = addr->GetIP();
   port = addr->GetPort();
  }
  else if (dat->GetRTCPDataAddress() != 0)
  {
   const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());
   ip = addr->GetIP();
   port = addr->GetPort()-1;
  }
  else
   return;
  
  RTPIPv4Address dest(ip,port);
  DeleteDestination(dest);
  
  struct in_addr inaddr;
  inaddr.s_addr = htonl(ip);
  std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl;
 }

 void OnRemoveSource(RTPSourceData *dat)
 {
  if (dat->IsOwnSSRC())
   return;
  if (dat->ReceivedBYE())
   return;
  
  uint32_t ip;
  uint16_t port;
  
  if (dat->GetRTPDataAddress() != 0)
  {
   const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());
   ip = addr->GetIP();
   port = addr->GetPort();
  }
  else if (dat->GetRTCPDataAddress() != 0)
  {
   const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());
   ip = addr->GetIP();
   port = addr->GetPort()-1;
  }
  else
   return;
  
  RTPIPv4Address dest(ip,port);
  DeleteDestination(dest);
  
  struct in_addr inaddr;
  inaddr.s_addr = htonl(ip);
  std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl;
 }
};

//
// The main routine
//

int main(void)
{
#ifdef WIN32
 WSADATA dat;
 WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
 
 MyRTPSession sess;
 uint16_t portbase,destport;
 uint32_t destip;
 std::string ipstr;
 int status,i,num,j=0;
 char sss[100];
 ZeroMemory(sss,100);

        // First, we'll ask for the necessary information
  //首先,我们请求必要的数据
  
 std::cout << "Enter local portbase:" << std::endl;
 std::cin >> portbase;
 std::cout << std::endl;
 
 std::cout << std::endl;
 std::cout << "Number of seconds you wish to wait:" << std::endl;
 std::cin >> num;
 
 // Now, we'll create a RTP session, set the destination
 // and poll for incoming data.
 //现在,我们将创建一个rtp会话,设置目标地址并且轮询流入的数据;
 
 RTPUDPv4TransmissionParams transparams;
 RTPSessionParams sessparams;
 
 // IMPORTANT: The local timestamp unit MUST be set, otherwise
 //            RTCP Sender Report info will be calculated wrong
 // In this case, we'll be just use 8000 samples per second
 //                                每秒8000个样本.
 
 /* 重要: */

 //sessparams.SetOwnTimestampUnit(1.0/8000.0);  
 sessparams.SetOwnTimestampUnit(1.0/10.0); 

 sessparams.SetAcceptOwnPackets(true);
 transparams.SetPortbase(portbase);
 status = sess.Create(sessparams,&transparams); 
 checkerror(status);
 
 for (i = 1 ; i <= num ; i++)
 {
  sess.BeginDataAccess();
  //std::cout<<"got packet!"<<std::endl;
  // check incoming packets 检查流入的包
  if (sess.GotoFirstSourceWithData())
  {
   do
   {
    RTPPacket *pack;
    
    while ((pack = sess.GetNextPacket()) != NULL)
    {
     memcpy(sss,pack->GetPacketData()+12,pack->GetPacketLength()-12);
     // You can examine the data here
     //printf("Got packet ! %d\n%d\n%s\n\n",j++,pack->GetPacketLength(),sss);
     printf("Got packet ! %d\n",j++);
     printf("packet len: %d \n",pack->GetPacketLength());
     printf("packet data : %s \n" , sss);
     for (int k=0;k<12;k++)
      printf("RTPHeader bytes: %x\n",pack->GetPacketData()[k]);
     // we don't longer need the packet, so
     // we'll delete it
     delete pack;
    }
   } while (sess.GotoNextSourceWithData());
  }
  
  sess.EndDataAccess();

#ifndef RTP_SUPPORT_THREAD
  status = sess.Poll();
  checkerror(status);
#endif // RTP_SUPPORT_THREAD
  
  RTPTime::Wait(RTPTime(1,0));
 }
 
 sess.BYEDestroy(RTPTime(10,0),0,0);

#ifdef WIN32
 WSACleanup();
#endif // WIN32
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值