rtp-rtcp实时传输协议实现课程设计

rtp-rtcp实时传输协议实现课程设计

ID:18217825

大小:54.00 KB

页数:20页

时间:2018-09-15

上传者:U-3770
rtp-rtcp实时传输协议实现课程设计_第1页
rtp-rtcp实时传输协议实现课程设计_第2页
rtp-rtcp实时传输协议实现课程设计_第3页
rtp-rtcp实时传输协议实现课程设计_第4页
rtp-rtcp实时传输协议实现课程设计_第5页
资源描述:

《rtp-rtcp实时传输协议实现课程设计》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

RTP-RTCP实时传输协议实现课程设计RTP-RTCP实时传输协议实现课程设计.txt45想洗澡吗?不要到外面等待下雨;想成功吗?不要空等机遇的到来。摘下的一瓣花能美丽多久?一时的放纵又能快乐多久?有志者要为一生的目标孜孜以求。少年自有少年狂,藐昆仑,笑吕梁;磨剑数年,今将试锋芒。自命不凡不可取,妄自菲薄更不宜。RTP-RTCP实时传输协议实现一、设计目的和意义  了解实时传输协议RTP和实时传输控制协议RTCP的基本原理;学习使用RTP数据报发送实时数据,并接收重组;学习实时数据传输控制基本方法;了解媒体内同步和媒体间同步的基本概念。二、设计原理  1、基本概念  RTP全名是Real-timeTransportProtocol(实时传输协议)。RTCP全名是Real-timeTransportControlProtocol,即实时传输控制协议。RTP定义在RFC1889中,是一种提供端对端传输服务的实时传输协议,用来支持网络服务中传输实时数据。RTCP用来监视服务质量和传送有关与会者的信息,主要功能是为应用程序提供会话质量或者广播性能质量的信息。多媒体网络通常把RTCP和RTP一起使用。RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。RTP的典型应用建立在UDP上,但也可以在TCP或ATM等其他协议之上工作。RTP为Internet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。RTCP负责管理传输质量在当前应用进程之间交换控制信息。在RTP会话期间,各参与者周期性地传送RTCP包,包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料,因此,服务器可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。RTP和RTCP配合使用,能以有效的反馈和最小的开销使传输效率最佳化,故特别适合传送网上的实时数据。  2、RTP工作机制   威胁多媒体数据传输的一个尖锐的问题就是不可预料数据到达时间。但是流媒体的传输是需要数据的适时的到达用以播放和回放。RTP协议就是提供了时间标签,序列号以及其它的结构用于控制适时数据的流放。在流的概念中”时间标签”是最重要的信息。发送端依照即时的采样在数据包里隐蔽的设置了时间标签。在接受端收到数据包后,就依照时间标签按照正确的速率恢复成原始的适时的数据。不同的媒体格式调时属性是不一样的。但是RTP本身并不负责同步,RTP只是传输层协议,为了简化运输层处理,提高该层的效率。将部分运输层协议功能(比如流量控制)上移到应用层完成。同步就是属于应用层协议完成的。它没有运输层协议的完整功能,不提供任何机制来保证实时地传输数据,不支持资源预留,也不保证服务质量。RTP报文甚至不包括长度和报文边界的描述。同时RTP协议的数据报文和控制报文的使用相邻的不同端口,这样大大提高了协议的灵活性和处理的简单性。  RTP协议和UDP二者共同完成运输层协议功能。UDP协议只是传输数据包,不管数据包传输的时间顺序。RTP的协议数据单元是用UDP分组来承载的。在承载RTP数据包的时候,有时候一帧数据被分割成几个包具有相同的时间标签,则可以知道时间标签并不是必须的。而UDP的多路复用让RTP协议利用支持显式的多点投递,可以满足多媒体会话的需求。  RTP协议虽然是传输层协议但是它没有作为OSI体系结构中单独的一层来实现。RTP协议通常根据一个具体的应用来提供服务,RTP只提供协议框架,开发者可以根据应用的具体要求对协议进行充分的扩展。  3、RTCP工作机制 当应用程序开始一个RTP会话时将使用两个端口:一个给RTP,一个给RTCP。RTP本身并不能为按顺序传送数据包提供可靠的传送机制,也不提供流量控制或拥塞控制,它依靠RTCP提供这些服务。在RTP的会话之间周期的发放一些RTCP包以用来传监听服务质量和交换会话用户信息等功能。RTCP包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料。因此,服务器可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。RTP和RTCP配合使用,它们能以有效的反馈和最小的开销使传输效率最佳化,因而特别适合传送网上的实时数据。根据用户间的数据传输反馈信息,可以制定流量控制的策略,而会话用户信息的交互,可以制定会话控制的策略。  RTCP主要有4个功能:用反馈信息的方法来提供分配数据的传送质量,这种反馈可以用来进行流量的拥塞控制,也可以用来监视网络和用来诊断网络中的问题;为RTP源提供一个永久性的CNAME(规范性名字)的传送层标志,因为在发现冲突或者程序更新重启时SSRC(同步源标识)会变,需要一个运作痕迹,在一组相关的会话中接收方也要用CNAME来从一个指定的与会者得到相联系的数据流(如音频和视频);根据与会者的数量来调整RTCP包的发送率;传送会话控制信息,如可在用户接口显示与会者的标识,这是可选功能。  4、RTP的协议层次  RTP(实时传输协议),顾名思义它是用来提供实时传输的,因而可以看成是传输层的一个子层。RTP被划分在传输层,它建立在UDP上。同UDP协议一样,为了实现其实时传输功能,RTP也有固定的封装形式。RTP用来为端到端的实时传输提供时间信息和流同步,但并不保证服务质量。服务质量由RTCP来提供。  不少人也把RTP归为应用层的一部分,这是从应用开发者的角度来说的。操作系统中的TCP/IP等协议栈所提供的是我们最常用的服务,而RTP的实现还是要靠开发者自己。因此从开发的角度来说,RTP的实现和应用层协议的实现没不同,所以可将RTP看成应用层协议。  5、RTP的会话过程  当应用程序建立一个RTP会话时,应用程序将确定一对目的传输地址。目的传输地址由一个网络地址和一对端口组成,有两个端口:一个给RTP包,一个给RTCP包,使得RTP/RTCP数据能够正确发送。RTP数据发向偶数的UDP端口,而对应的控制信号RTCP数据发向相邻的奇数UDP端口(偶数的UDP端口+1),这样就构成一个UDP端口对。RTP的发送过程如下,接收过程则相反。  1)RTP协议从上层接收流媒体信息码流(如H.263),封装成RTP数据包;RTCP从上层接收控制信息,封装成RTCP控制包。  2)RTP将RTP 数据包发往UDP端口对中偶数端口;RTCP将RTCP控制包发往UDP端口对中的接收端口。  6、RTP的封装  一个协议的封装是为了满足协议的功能需求的。从前面提出的功能需求,可以推测出RTP封装中应该有同步源和时戳等字段,但更为完整的封装是什么样子呢?请看图1。VPXCCMPT序列号时戳同步信源(SSRC)标识符特约信源(CSRC)标识符图1RTP的头部格式  版本号(V):2比特,用来标志使用的RTP版本。  填充位(P):1比特,如果该位置位,则该RTP包的尾部就包含附加的填充字节。  扩展位(X):1比特,如果该位置位的话,RTP固定头部后面就跟有一个扩展头部。  CSRC计数器(CC):4比特,含有固定头部后面跟着的CSRC的数目。  标记位(M):1比特,该位的解释由配置文档(Profile)来承担.  载荷类型(PT):7比特,标识了RTP载荷的类型。  序列号(SN):16比特,发送方在每发送完一个RTP包后就将该域的值增加1,接收方可以由该域检测包的丢失及恢复包序列。序列号的初始值是随机的。   时间戳:32比特,记录了该包中数据的第一个字节的采样时刻。在一次会话开始时,时间戳初始化成一个初始值。即使在没有信号发送时,时间戳的数值也要随时间而不断地增加(时间在流逝嘛)。时间戳是去除抖动和实现同步不可缺少的。  同步源标识符(SSRC):32比特,同步源就是指RTP包流的来源。在同一个RTP会话中不能有两个相同的SSRC值。该标识符是随机选取的RFC1889推荐了MD5随机算法。  贡献源列表(CSRCList):0~15项,每项32比特,用来标志对一个RTP混合器产生的新包有贡献的所有RTP包的源。由混合器将这些有贡献的SSRC标识符插入表中。SSRC标识符都被列出来,以便接收端能正确指出交谈双方的身份。7、RTCP的封装  RTCP的主要功能是:服务质量的监视与反馈、媒体间的同步,以及多播组中成员的标识。在RTP会话期间,各参与者周期性地传送RTCP包。RTCP包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料,因此,各参与者可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。RTP和RTCP配合使用,它们能以有效的反馈和最小的开销使传输效率最佳化,因而特别适合传送网上的实时数据。RTCP也是用UDP来传送的,但RTCP封装的仅仅是一些控制信息,因而分组很短,所以可以将多个RTCP分组封装在一个UDP包中。RTCP有如下五种分组。表1RTCP的5种分组类型类型缩写表示用途200SR(SenderReport)发送端报告201RR(ReceiverReport)接收端报告 202SDES(SourceDescriptionItems)源点描述203BYE结束传输204APP特定应用8、RTP协议传输数据流的收发程序流程图        发送接收获得接收端的IP地址和端口号获得用户指定的端口号      创建RTP会话创建RTP会话指定RTP数据接收端设置接收模式    设置RTP会话默认参数接受RTP数据      发送流媒体数据检索RTP数据源获取RTP数据报删除RTP数据报图3RTP协议传输数据流的收发程序流程图三、详细设计步骤1、环境搭建  通过RTP协议传输数据流的收发程序,进行实时流媒体数据传输,需要使用JRTPLIB。JRTPLIB是一个用C++语言实现的RTP库,目前已经可以运行在Windows、Linux、FreeBSD、Solaris、Unix和VxWorks等多种操作系统上。  先要将JRTPLIB库在windows系统下进行编译,之后编译的RTP协议传输数据流的收发源程序,就可运行了。2、初始化   在使用JRTPLIB进行实时流媒体数据传输之前,首先应该生成RTPSession类的一个实例来表示此次RTP会话,然后调用Create()方法来对其进行初始化操作。RTPSession类的Create()方法只有一个参数,用来指明此次RTP会话所采用的端口号。3、数据发送  当RTP会话成功建立起来之后,接下来就可以开始进行流媒体数据的实时传输了。首先需要设置好数据发送的目标地址,RTP协议允许同一会话存在多个目标地址,这可以通过调用RTPSession类的AddDestination()、DeleteDestination()和ClearDestinations()方法来完成。目标地址全部指定之后,接着就可以调用RTPSession类的SendPacket()方法,向所有的目标地址发送流媒体数据。SendPacket()最典型的用法是类似于下面的语句,其中第一个参数是要被发送的数据,而第二个参数则指明将要发送数据的长度,再往后依次是RTP负载类型、标识和时戳增量。例如:sess.SendPacket(buffer,5,0,false,10);  对于同一个RTP会话来讲,负载类型、标识和时戳增量通常来讲都是相同的,JRTPLIB允许将它们设置为会话的默认参数,这是通过调用RTPSession类的SetDefaultPayloadType()、SetDefaultMark()等方法来完成的。  为RTP会话设置这些默认参数的好处是可以简化数据的发送。例如,如果为RTP会话设置了默认参数:sess.SetDefaultPayloadType(0);sess.SetDefaultMark(false);sess.SetDefaultTimeStampIncrement(10);  之后在进行数据发送时只需指明要发送的数据及其长度就可以了。例如:sess.SendPacket(buffer,5);4、数据接收   对于流媒体数据的接收端,首先需要调用PollData()方法来接收发送过来的RTP或者RTCP数据报。由于同一个RTP会话中允许有多个参与者(源),因此既可以通过调用GotoFirstSource()和GotoNextSource()方法来遍历所有的源,也可以通过调用GotoFisstSourceWithDat()和GotoNextSourceWithData()方法来遍历那些携带有数据的源。在从RTP会话中检测出有效的数据源之后,接下去就可以调用RTPSession类的GetNextPacket()方法从中抽取RTP数据报,当接收到的RTP数据报处理完之后,要及时释放。下面的代码示范了该如何对接收到的RTP数据报进行处理:do{sess.BeginDataAccess();if(sess.GotoFirstSourceWithData()){do{RTPPacket*pack;uint8_t*data;size_tlength;if((outfile=open("/mnt/hgfs/download/temp1.YUV",O_WRONLY|O_CREAT|O_APPEND))<0){perror("openoutfileerror");return-1;}while((pack=sess.GetNextPacket())!=NULL){data=pack->GetPayloadData();length=pack->GetPayloadLength();if((write(outfile,data,length))<0)//将接收到的图片信息写入文中。{perror("writeoutfileerror;");return-1; }sess.DeletePacket(pack);}}while(sess.GotoNextSourceWithData());}sess.EndDataAccess();close(outfile);   JRTPLIB为RTP数据报定义了3种接收模块,通过调用RTPSession类的SetReceiveMode()方法可以设置下列这些接收模式:RECEIVEMODE_ALL:缺省的接收模式,所有到达的RTP数据报都将被接受;RECEIVEMODE_IGNORESOME:除了某些特定的发送者之外,所有到达的RTP数据报都将被接受,而被拒绝的发送者列表可以通过调用AddToIgnoreList(),DeleteFromIgnoreList()和ClearIgnoreList()方法来进行设置; RECEIVEMODE_ACCEPTSOME:除了某些特定的发送者之外,所有到达的RTP数据报都将被拒绝,而被接受的发送者列表可以通过调用AddToAcceptList(),DeleteFromAcceptList和ClearAcceptList()方法来进行设置。四、设计结果及分析1、网络实时传输协议的测试程序rtpclient.cpprtpclient.pp的功能是在同一个端口收发数据包,所以它不仅能把数据包发送出去,还能收到发送的数据包并解析出数据包中的内容。程序如下://rtpclient.pp#pragmacomment(lib,"jrtplib.lib")#pragmacomment(lib,"jthread.lib")#pragmacomment(lib,"WS2_32.lib")#include"header/rtpsession.h"#include"header/rtppacket.h" #include"header/rtpudpv4transmitter.h"#include"header/rtpipv4address.h"#include"header/rtpsessionparams.h"#include"header/rtperrors.h"#ifndefWIN32#include#include#else#include#endif//WIN32#include#include#include#includevoidcheckerror(intrtperr){if(rtperr<0){std::cout<<"ERROR:"<>portbase;std::cout<>ipstr;destip=inet_addr(ipstr.c_str());if(destip==INADDR_NONE){std::cerr<<"BadIPaddressspecified"<>destport;std::cout<>num;RTPUDPv4TransmissionParamstransparams;RTPSessionParamssessparams;sessparams.SetOwnTimestampUnit(1.0/10.0);sessparams.SetAcceptOwnPackets(true);transparams.SetPortbase(portbase);status=sess.Create(sessparams,&transparams);checkerror(status); RTPIPv4Addressaddr(destip,destport);status=sess.AddDestination(addr);checkerror(status);for(i=1;i<=num;i++){printf(" Sendingpacket%d/%d ",i,num);//发送数据1234567890status=sess.SendPacket((void*)"1234567890",10,0,false,10);checkerror(status);sess.BeginDataAccess();//检查发送过来的数据包if(sess.GotoFirstSourceWithData()){do{RTPPacket*pack;while((pack=sess.GetNextPacket())!=NULL){printf("Gotpacket! ");std::cout<<"Gotpacketwith"<<"extendedsequencenumber"<GetExtendedSequenceNumber()<<"fromSSRC"<GetSSRC()<GetPayloadLength();pfBuffer=(unsignedchar*)pack->GetPayloadData();pBuffer=newBYTE[dataLength+1]; memcpy(pBuffer,pfBuffer,dataLength);pBuffer[dataLength]=0;std::cout<#include#include"rtpsession.h" //错误处理函数voidcheckerror(interr){if(err<0){char*errstr=RTPGetErrorString(err);printf("Error:%s ",errstr);exit(-1);}}intmain(intargc,char**argv){RTPSessionsess;unsignedlongdestip;intdestport;intportbase=6000;intstatus,index;charbuffer[128];if(argc!=3){printf("Usage:./senderdestipdestport ");return-1;}//获得接收端的IP地址和端口号destip=inet_addr(argv[1]);if(destip==INADDR_NONE){printf("BadIPaddressspecified. ");return-1;}destip=ntohl(destip);destport=atoi(argv[2]);//创建RTP会话status=sess.Create(portbase); checkerror(status);//指定RTP数据接收端status=sess.AddDestination(destip,destport);checkerror(status);//设置RTP会话默认参数sess.SetDefaultPayloadType(0);sess.SetDefaultMark(false);sess.SetDefaultTimeStampIncrement(10);//发送流媒体数据index=1;do{sprintf(buffer,"%d:RTPpacket",index++);sess.SendPacket(buffer,strlen(buffer));printf("Sendpacket! ");}while(1);return0;}接收程序如下://receiver.cpp#include#include"rtpsession.h"#include"rtppacket.h"//错误处理函数voidcheckerror(interr){if(err<0){char*errstr=RTPGetErrorString(err);printf("Error:%s ",errstr);exit(-1);}} intmain(intargc,char**argv){RTPSessionsess;intlocalport;intstatus;if(argc!=2){printf("Usage:./senderlocalport ");return-1;}//获得用户指定的端口号localport=atoi(argv[1]);//创建RTP会话status=sess.Create(localport);checkerror(status);do{//接受RTP数据status=sess.PollData();//检索RTP数据源if(sess.GotoFirstSourceWithData()){do{RTPPacket*packet;//获取RTP数据报while((packet=sess.GetNextPacket())!=NULL){printf("Gotpacket! ");//删除RTP数据报deletepacket;}}while(sess.GotoNextSourceWithData());}}while(1);return0; }  发送程序sender.cpp,它负责向用户指定的IP地址和端口,不断地发送RTP数据包。接收程序receiver.cpp,它负责从指定的端口不断地读取RTP数据包。3、在调试程序中遇到的问题及出现问题的原因和解决办法  (1)Cannotopenincludefile:'rtpsession.h':Nosuchfileordirectory.即找不到头文件rtpsession.h。原因:是在VC++编译源程序的工作空间中没有包含rtpsession.h头文件。解决办法:我们把JRTPLIB中的所有头文件都放到headerrtpclient.cpp源码改一下#include"rtpsession.h"改成#inclu文件夹中,再把header文件夹放到rtpclient.cpp所在的工作空间中。再把rtpclient.cpp源码改一下,#include"rtpsession.h"改成#include"header/rtpsession.h",同样的,把其它头文件包含的都改过来。(2)'fd_set'redefinitionwinsock2.h.  原因:是因为winsock.h和winsock2.h中有重定义的部分。  解决办法:在引用之前,加上预处理指令:  #defineWIN32_LEAN_AND_MEAN(3)errorLNK2019:无法解析的外部符号"public:virtual__thiscallRTPSession::~RTPSession(void)"(??1RTPSession@@UAE@XZ),该符号在函数_main中被引用。  原因:问题出在缺少lib库jrtplib.lib。由于没有找到lib库,也就是链接设置中没有设置所需要的lib。  解决办法:在源文件头部添加如下指令:  #pragmacomment(lib,"jrtplib.lib")  #pragmacomment(lib,"jthread.lib")(4)msvcprtd.lib(MSVCP71D.dll):errorLNK2005:"public:__thiscallstd::basic_string,classstd::allocator>::~basic_string,classstd::allocator>(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ)已经在example2.obj中定义  解决方法:设置VC运行库(C/C++->CodeGeneration->UseRuntimelibrary选MultiThreadedDLL.???(5)无法解析的外部符号__imp__WSACleanup@0,该符号在函数_main中被引用。  解决方法:在源文件头部添加#pragmacomment(lib,"ws2_32.lib")????五、体会  通过做这次程序设计,我对实时传输协议RTP和实时传输控制协议RTCP的基本原理有了更深刻的认识,在学习实时传输协议与流媒体时有许多地方不理解比如通过RTP协议传输数据流的收发程序是怎么编写等,通过重新复习相关知识和查阅资料,编写程序对以前一些迷惑的地方理解的更透彻,学会了理论与实践相结合的方法。理论是实践的基础,只有掌握了相关的理论知识才能更好更轻松的实践。当理论某些细节不是很理解时,可以通过编程仿真来实现,将仿真结果与理论结合起来进行对比理解这样会容易点。不过这限于一些小的地方,当很多都不懂时,就不行了,因为你很多地方不懂时就不能实现编程了。总之,在本次的专业方向设计过程中学习到了许多书本上没有的知识,同时也提高了自己在浩瀚的网络资源中查找有用资源的能力。六、参考文献[1]王汝言.多媒体通信技术.西安电子科技大学出版社,2004.2[2]王昕.多媒体通信.现代电子科技,1998,(8):1~9[3]李小平,曲大成.多媒体网络通信.北京:北京理工大学出版社,2001[4]http://research.edm.uhasselt.be/~jori/page/index.php?n=CS.Jrtplib[5]http://blog.csdn.net/heanyu/archive/2010/12/15/6077827.aspx

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭