基於RTP協議的資料通訊程式

來源:互聯網
上載者:User

最近調試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;
}

 

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.