1.单播
单播是一种“一对一”模式,在单播通信方式下,当一端发送数据报到一个指定的主机时,首先可能会引发ARP把目的IP地址映射为MAC地址,然而ARP就是基于广播模式的实现。当以太网帧到达一个主机时,以太网接口便会把自己的MAC地址与帧中的MAC地址相比较,如果相符,以太网接口便会接收该帧,并按协议栈向上递交,如果不想符,该帧将会忽略该帧。其他的以太网接口做同样的操作,最后接收该帧的只有一个主机。在此之后,然后以太网帧向上递交到IP层目的主机会核对IP分组中的目的IP与本机IP(多宿主机),符合,根据协议类型向上递交到传输层相应的协议处理这即时单播通信的过程。典型的TCP通信就是单播模式的。
单播在网络中得到了广泛的应用,网络上绝大部分的数据都是以单播的形式传输的,只是一般网络用户不知道而已。例如,你在收发电子邮件、浏览网页时,必须与邮件服务器、Web服务器建立连接,此时使用的就是单播数据传输方式。但是通常使用“点对点通信”(Point to Point)代替“单播”,因为“单播”一般与“多播”和“广播”相对应使用
2.多播
多播是一种“一对一组”的模式,也就时加入同一个组的主机才会接收到数据,他综合了单播和广播的优点,可以只对特定的主机进行通信,其他的主机通信不受影响。多播通常被指IP多播,IP多播是一种通过使用一个多播地址将数据在同一时间以高效的方式发往处于TCP/IP网络上的多个接收者的协议。但是对于IP多播,扩容不容易。
“多播”也可以称为“组播”,在网络技术的应用并不是很多,网上视频会议、网上视频点播特别适合采用多播方式。因为如果采用单播方式,逐个节点传输,有多少个目标节点,就会有多少次传送过程,这种方式显然效率极低,是不可取的;如果采用不区分目标、全部发送的广播方式,虽然一次可以传送完数据,但是显然达不到区分特定数据接收对象的目的。采用多播方式,既可以实现一次传送所有目标节点的数据,也可以达到只对特定对象传送数据的目的。IP网络的多播一般通过多播IP地址来实现。多播IP地址就是D类IP地址,即224.0.0.0至239.255.255.255之间的IP地址。
3.广播
广播时一种“一对所有”模式,在广播模式下,该以太网帧被局域网中所有的以太网接口接收,并向上递交到传输层,如果指定的端口开启并绑定相应的应用进程时,应用进程就会处理该数据报,如果端口没有任何进程绑定,传输层就会丢弃该数据报。该主机并不会发送一个ICMP数据不可达的消息,否则会导致广播风暴。
广播风暴就是网络长时间被大量的广播数据包所占用,正常的点对点通信无法正常进行,外在表现为网络速度奇慢无比。出现广播风暴的原因有很多,一块有故障的网卡,就可能长时间向网络上发送广播包而导致广播风暴。“广播”在网络中的应用较多,如客户机通过DHCP自动获得IP地址的过程就是通过广播来实现的。
发送端程序:
/*=============================================================================
* FileName: jrtplib_send.cpp
* Desc: sending packets to destination port
* Author: licaibiao
* LastChange: 2017-04-10
* =============================================================================*/
#include <jrtplib3/rtpsession.h>
#include <jrtplib3/rtpudpv4transmitter.h>
#include <jrtplib3/rtpipv4address.h>
#include <jrtplib3/rtpsessionparams.h>
#include <jrtplib3/rtperrors.h>
#include <jrtplib3/rtplibraryversion.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
//#define UNICAST
#define MULTICAST
//#define BROADCAST
using namespace jrtplib;
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
int main(void)
{
int i;
int num;
int status;
RTPSession sess;
uint16_t portbase = 6666;
uint16_t destport = 6664;
#ifdef UNICAST
uint8_t destip[]={192,168,0,6};
#endif
#ifdef MULTICAST
uint8_t destip[]={224,0,0,100};
#endif
#ifdef BROADCAST
uint8_t destip[]={192,168,0,255};
#endif
std::cout << "Number of packets you wish to be sent:" << std::endl;
std::cin >> num;
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/10.0);
sessparams.SetAcceptOwnPackets(true);
transparams.SetPortbase(portbase);
#ifdef MULTICAST
transparams.SetMulticastTTL(255);
#endif
status = sess.Create(sessparams,&transparams);
checkerror(status);
#ifdef MULTICAST
status = sess.SupportsMulticasting();
checkerror(status);
#endif
RTPIPv4Address addr(destip,destport);
status = sess.AddDestination(addr);
checkerror(status);
for (i = 1 ; i <= num ; i++)
{
printf("\nSending packet %d/%d\n",i,num);
status = sess.SendPacket((void *)"1234567890",10,0,false,10);
checkerror(status);
RTPTime::Wait(RTPTime(1,0));
}
sess.BYEDestroy(RTPTime(10,0),0,0);
return 0;
}
接收端程序:
/*=============================================================================
* FileName: jrtplib_receive.cpp
* Desc: receive packet and print out the payloaddata
* Author: licaibiao
* LastChange: 2017-04-10
* =============================================================================*/
#include <jrtplib3/rtpsession.h>
#include <jrtplib3/rtpudpv4transmitter.h>
#include <jrtplib3/rtpipv4address.h>
#include <jrtplib3/rtpsessionparams.h>
#include <jrtplib3/rtperrors.h>
#include <jrtplib3/rtplibraryversion.h>
#include <jrtplib3/rtppacket.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#define MULTICAST
using namespace jrtplib;
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
int main(void)
{
RTPSession sess;
uint16_t portbase = 6664;
int status;
bool done = false;
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/10.0);
sessparams.SetAcceptOwnPackets(true);
transparams.SetPortbase(portbase);
status = sess.Create(sessparams,&transparams);
checkerror(status);
#ifdef MULTICAST
uint8_t ip[]={224,0,0,100};
RTPIPv4Address addr(ip,portbase);
status = sess.SupportsMulticasting();
checkerror(status);
status = sess.JoinMulticastGroup(addr);
checkerror(status);
#endif
sess.BeginDataAccess();
RTPTime delay(0.020);
RTPTime starttime = RTPTime::CurrentTime();
while (!done)
{
status = sess.Poll();
checkerror(status);
if (sess.GotoFirstSourceWithData())
{
do
{
RTPPacket *pack;
while ((pack = sess.GetNextPacket()) != NULL)
{
std::cout << pack->GetPayloadData() << std::endl;
sess.DeletePacket(pack);
}
} while (sess.GotoNextSourceWithData());
}
RTPTime::Wait(delay);
RTPTime t = RTPTime::CurrentTime();
t -= starttime;
if (t > RTPTime(60.0))
done = true;
}
#ifdef MULTICAST
sess.LeaveAllMulticastGroups();
#endif
sess.EndDataAccess();
delay = RTPTime(10.0);
sess.BYEDestroy(delay,0,0);
return 0;
}
程序通过宏UNICAST, MULTICAST, BROADCAST 来区分是单播,多播,还是广播。程序运行结果如下:
发送端结果:
licaibiao@lcb:~/test/RTP/test_jrtplib$ make
g++ jrtplib_send.cpp -o test -ljrtp
licaibiao@lcb:~/test/RTP/test_jrtplib$ ls
jrtplib_send.cpp Makefile test
licaibiao@lcb:~/test/RTP/test_jrtplib$ ./test
Number of packets you wish to be sent:
50
Sending packet 1/50
Sending packet 2/50
Sending packet 3/50
Sending packet 4/50
Sending packet 5/50
Sending packet 6/50
Sending packet 7/50
接收端运行结果:
g++ jrtplib_receive.cpp -o test -ljrtp
licaibiao@ubuntu:~/test/RTP_TEST/JRTPLIB/biao$ ./test
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
......
RTP协议一般用于单播和多播。至于广播,理论上是只要把单播最后的IP地址改为255就可以了,但是实际在我得电脑中测试,广播数据发送不出来。认真的查看了JRTPLIB,它应该是不支持广播的,如果需要广播,需要自己再修改。
上面代码可以在这里下载:linux 调用jrtplib实现单播,多播,广播
本文参考博客:Qt调用jrtplib实现单播、多播和广播_qt jrtplib-CSDN博客