</pre>文章里面主要是把发送端课接收端代码的实现提了出来,和重要函数里的源码贴出来辅助学习,看到网上有人说好久做不出来,建议看看对应加入组播的源码,注意细节,话不多说,代码直接贴出来,各位朋友有意见多多交流。<p></p><p>发送端:</p><pre code_snippet_id="1677192" snippet_file_name="blog_20160510_2_5720022" name="code" class="cpp">#include "rtpsession.h" #include "rtpudpv4transmitter.h" #include "rtpipv4address.h" #include "rtpsessionparams.h" #include "rtperrors.h" #include "rtppacket.h" #ifndef WIN32 #include <netinet/in.h> #include <arpa/inet.h> #else #include <winsock2.h> #include<windows.h> #endif // WIN32 #include <stdlib.h> #include <stdio.h> #include <iostream> #include <string> using namespace jrtplib; using namespace std; void checkerror(int rtperr) { if(rtperr<0) { cout<<"ERROR:"<<RTPGetErrorString(rtperr)<<endl; exit(-1); } } int main() { #ifdef WIN32 WSADATA dat; WSAStartup(MAKEWORD(2,2),&dat); #endif // WIN32 list<uint32_t> localip; RTPSession sess; uint16_t portbase=6666,destport=8888; uint32_t destip,srcip; string ipstr="239.255.0.1"; string ipsrc="114.212.118.99"; int status,i,num; destip=inet_addr(ipstr.c_str());//将字符串转换为32位网络字节序。 srcip=inet_addr(ipsrc.c_str()); if(destip==INADDR_NONE) { cout<<"bad destip address"<<endl; exit(-1); } destip=ntohl(destip);//将32位网络字节序转换成主机字节序 srcip=ntohl(srcip); localip.push_back(srcip); //设置传输参数和会话参数 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) sessparams.SetOwnTimestampUnit(1.0/8000); sessparams.SetAcceptOwnPackets(true); transparams.SetPortbase(portbase); transparams.SetLocalIPList(localip); transparams.SetMulticastInterfaceIP(srcip); transparams.SetMulticastTTL(255); status = sess.Create(sessparams,&transparams); checkerror(status); RTPIPv4Address addr(destip,destport); status=sess.AddDestination(addr); checkerror(status); if(sess.SupportsMulticasting()) { cout<<"支持组播"<<endl; } char *p=new char[100]; i=0; sess.SetDefaultPayloadType(96); sess.SetDefaultMark(false); sess.SetDefaultTimestampIncrement(160); while(1) { i++; memset(p,0,100); sprintf(p,"bababba:%d",i); status=sess.SendPacket(p,100); cout<<i<<endl;; } sess.BYEDestroy(RTPTime(10,0),0,0); return 0; }
</pre><pre code_snippet_id="1677192" snippet_file_name="blog_20160510_4_7431889" name="code" class="cpp">接收端:
<pre name="code" class="cpp"> #include "rtpsession.h" #include "rtpudpv4transmitter.h" #include "rtpipv4address.h" #include "rtpsessionparams.h" #include "rtperrors.h" #include "rtppacket.h" #ifndef WIN32 #include <netinet/in.h> #include <arpa/inet.h> #else #include <winsock2.h> #include<windows.h> #endif // WIN32 #include <stdlib.h> #include <stdio.h> #include <iostream> #include <string> using namespace jrtplib; using namespace std; void checkerror(int rtperr) { if(rtperr<0) { cout<<"ERROR:"<<RTPGetErrorString(rtperr)<<endl; exit(-1); } } int main() { #ifdef WIN32 WSADATA dat; WSAStartup(MAKEWORD(2,2),&dat); #endif // WIN32 RTPUDPv4TransmissionParams transparams; RTPSessionParams sessparams; list<uint32_t> localip; RTPSession sess; uint16_t portbase=8888; uint32_t destip,srcip; string ipstr="239.255.0.1"; string ipsrc="114.212.114.200"; int status,i,num; destip=inet_addr(ipstr.c_str());//将字符串转换为32位网络字节序。 srcip=inet_addr(ipsrc.c_str()); destip=ntohl(destip);//将32位网络字节序转换成主机字节序 srcip=ntohl(srcip); localip.push_back(srcip); sessparams.SetOwnTimestampUnit(1.0/8000); sessparams.SetAcceptOwnPackets(true); transparams.SetPortbase(portbase); //transparams.SetLocalIPList(localip); transparams.SetBindIP(srcip); transparams.SetMulticastInterfaceIP(srcip); RTPIPv4Address addr(destip,portbase); status = sess.Create(sessparams,&transparams); checkerror(status); status=sess.SupportsMulticasting(); checkerror(status); status=sess.JoinMulticastGroup(addr); checkerror(status); //sess.SetDefaultPayloadType(96); //sess.SetDefaultMark(false); //sess.SetDefaultTimestampIncrement(160); while(1) { sess.BeginDataAccess(); if(sess.GotoFirstSourceWithData()) { do { RTPPacket *pack; uint32_t packetLen; uint8_t *packetData; uint8_t j = 11; while ((pack = sess.GetNextPacket()) != NULL) { packetLen = pack->GetPacketLength() - 1; packetData = pack->GetPacketData(); printf("RECV data: "); while(j++ < packetLen) { printf("%c", *(packetData + j)); } printf("\n"); sess.DeletePacket(pack); } }while(sess.GotoNextSourceWithData()); } sess.EndDataAccess(); } return 0; }
重要的源码
int RTPUDPv4Transmitter::JoinMulticastGroup(const RTPAddress &addr) { if (!init) return ERR_RTP_UDPV4TRANS_NOTINIT; MAINMUTEX_LOCK int status; if (!created) { MAINMUTEX_UNLOCK return ERR_RTP_UDPV4TRANS_NOTCREATED; } if (addr.GetAddressType() != RTPAddress::IPv4Address) { MAINMUTEX_UNLOCK return ERR_RTP_UDPV4TRANS_INVALIDADDRESSTYPE; } const RTPIPv4Address &address = (const RTPIPv4Address &)addr; uint32_t mcastIP = address.GetIP(); if (!RTPUDPV4TRANS_IS_MCASTADDR(mcastIP)) { MAINMUTEX_UNLOCK return ERR_RTP_UDPV4TRANS_NOTAMULTICASTADDRESS; } status = multicastgroups.AddElement(mcastIP); if (status >= 0) { RTPUDPV4TRANS_MCASTMEMBERSHIP(rtpsock,IP_ADD_MEMBERSHIP,mcastIP,status); if (status != 0) { multicastgroups.DeleteElement(mcastIP); MAINMUTEX_UNLOCK return ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP; } RTPUDPV4TRANS_MCASTMEMBERSHIP(rtcpsock,IP_ADD_MEMBERSHIP,mcastIP,status); if (status != 0) { RTPUDPV4TRANS_MCASTMEMBERSHIP(rtpsock,IP_DROP_MEMBERSHIP,mcastIP,status); multicastgroups.DeleteElement(mcastIP); MAINMUTEX_UNLOCK return ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP; } } MAINMUTEX_UNLOCK return status; } #define RTPUDPV4TRANS_MCASTMEMBERSHIP(socket,type,mcastip,status) { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = htonl(mcastip); mreq.imr_interface.s_addr = htonl(mcastifaceIP); status = setsockopt(socket,IPPROTO_IP,type,(const char *)&mreq, sizeof(struct ip_mreq)); } 里面的mcastifaceIP是由自己提前设定的 在create函数里面 bindIP = params->GetBindIP(); mcastifaceIP = params->GetMulticastInterfaceIP(); memset(&addr,0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(params->GetPortbase()); addr.sin_addr.s_addr = htonl(bindIP); if (bind(rtpsock,(struct sockaddr *)&addr,sizeof( struct sockaddr_in)) != 0) { RTPCLOSE(rtpsock); RTPCLOSE(rtcpsock); MAINMUTEX_UNLOCK return ERR_RTP_UDPV4TRANS_CANTBINDRTPSOCKET; } memset(&addr,0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(params->GetPortbase()+1); addr.sin_addr.s_addr = htonl(bindIP); if (bind(rtcpsock,(struct sockaddr *)&addr,sizeof( struct sockaddr_in)) != 0) { RTPCLOSE(rtpsock); RTPCLOSE(rtcpsock); MAINMUTEX_UNLOCK return ERR_RTP_UDPV4TRANS_CANTBINDRTCPSOCKET; }
具体的实现好的代码下载地址,希望对各位有用,在vs2012下运行:
http://download.csdn.net/detail/u010289908/9515174
时间: 2024-10-14 15:02:08