今天我这篇文章是基于这两篇文章修改了下:
http://blog.csdn.net/chenpeng19910926/article/details/51782821
http://blog.csdn.net/chenhanzhun/article/details/42006385
概述
主机可采用的通信方式有如下三种:
- 单播:单台主机与单台主机之间的数据通信;
- 广播:单台主机向网络中所有主机发送数据报的过程;
- 多播:单台主机向选定的一组主机发送数据报的过程;
在网络协议中 IP 地址有三种方式,即为单播地址、广播地址 以及 多播地址。假设多个主机上的共享信道网络是以太网,每个以太网帧包含源主机和目的主机的以太网地址。若目的地址仅指定单个接收接口,则称为单播,在单播方式下,任意两台主机之间的通信不会干扰网内其他主机。若目的地址包含网上的所有主机的接收接口时,即一个主机要向网上所有主机发送帧,则称为广播。若一个主机把帧发送给属于多播组的多个主机,则称为多播。广播和多播仅应用于 UDP,可以将数据报文同时传给多个接收者,而 TCP 是一个面向连接的字节流协议,意味着只能运行于两个主机(由 IP 地址确定)内的两个进程(由端口号确定)之间的一条连接。
首先了解下信道传送的帧在主机的过滤过程,如下图所示:
信道传送的帧在主机的过滤过程:
- 首先,网卡查看由信道传送给来的帧,确定是否接收该帧,对该帧进行检验和,若检验和出错,则将其丢弃,若检验和正确,则将其传送给设备驱动程序;
- 设备驱动程序也对来自接口卡的帧进行过滤,首先确认该帧指定的协议类型,然后进行多播过滤检测该主机是否属于多播地址说明的多播组,若帧的指定协议类型为 IP 协议,则将其传给 IP 层;
- 在 IP 层中根据 IP 地址中的源地址和目的地址进程过滤检测,若正常则将其传送给下一层,假设是 UDP 层;
- 每次 UDP 接收来自 IP 传送来的数据报,再根据端口号进行数据报过滤,若当前没有使用该端口号的进程,则将其丢弃,并产生一个 ICMP 不可达报文,若是检验和错误,则直接将其丢弃;
广播
广播可分为两大类:定向的广播 和 受限的广播
- 受限的广播:受限的广播地址是 255.255.255.255。该地址用于主机配置过程中 IP 数据报的目的地址,此时,主机并不知道它所在的网络掩码,甚至它的 IP 地址都不知道。任何情况下,路由器都不能转发目的地址为受限的广播地址的数据报,因此,受限的广播地址的数据报只能出现在本地网络中。
- 定向的广播:定向广播是将数据包发送到向本网络之外的特定网络所有主机,定向广播的目的地址是定向网络的广播地址;
- 指向网络的广播:指向网络的广播地址是主机号全为 1 的地址,例如 A 类网络广播地址是netid.255.255.255,其中 netid 是 A 类网络的网络号。路由器必须转发指向网络的广播。
- 指向子网的广播:指向子网的广播地址为主机号全为 1 且有特定子网号的地址。作为子网直接广播地址的 IP 地址需要了解子网掩码。
- 指向所有子网的广播:指向所有子网的广播也需要连接目的网络的子网掩码,以便与指向网络的广播区分开来。指向所有子网的广播地址的子网号即主机全是 1。
多播
多播也称为组播,组播是向指定的一组主机发送数据包。与单播相比,提高了发送数据包的效率,与广播相比,减少了网络流量。与广播不同的是,要实现组播需要在接受组播的客户机上安装相应的客户端程序。能接收发送一个特定多播组地址数据的主机集合称为主机组。
IP 多播提供两类服务:
- 向多个目的地址传送数据;
- 客户对服务器的请求;
总结
单播是将数据报发给特定的单台主机,广播是将数据报发送给网络中所有的主机,而多播是将数据报发送给网络的一个主机组。广播的缺点是网络中的所有主机都必须处理数据报,而多播不需要,减少了网络流量。
我上篇文章UDP的数据传输实际上是广播的传输形式,现在详细讲多播。
广播发送数据流程:
同一网段所有主机都能接收,前提是端口要监听
客户端发送广播,开启端口监听的服务端接收并打印消息
多播发送数据流程:
多播数据报套接字类用于发送和接收 IP 多播包。MulticastSocket 是一种 (UDP) DatagramSocket,它具有加入 Internet 上其他多播主机的“组”的附加功能。
多播组通过 D 类 IP 地址和标准 UDP 端口号指定。D 类 IP 地址在 224.0.0.0
和 239.255.255.255
的范围内(包括两者)。地址 224.0.0.0 被保留,不应使用。
可以通过首先使用所需端口创建 MulticastSocket,然后调用 joinGroup(InetAddress groupAddr)
方法来加入多播组:(以上是jdk-doc的说明,补充如下:服务器和客户端必须都要加入相同的组播地址才可以)
服务器端程序:
//接受组播和发送组播的数据报服务都要把组播地址添加进来
String host = "225.0.0.1";//多播地址
int port = 9998;
int length = 1024;
byte[] buf = new byte[length];
MulticastSocket ms = null;
DatagramPacket dp = null;
StringBuffer sbuf = new StringBuffer();
try {
ms = new MulticastSocket(port);
dp = new DatagramPacket(buf, length);
//加入多播地址
InetAddress group = InetAddress.getByName(host);
ms.joinGroup(group);
System.out.println("监听多播端口打开:");
ms.receive(dp);
ms.close();
int i;
for(i=0;i<1024;i++){
if(buf[i] == 0){
break;
}
sbuf.append((char) buf[i]);
}
System.out.println("收到多播消息:" + sbuf.toString());
} catch (IOException e) {
e.printStackTrace();
}
客户端程序
String host = "225.0.0.1";//多播地址
int port = 9998;
String message = "test-multicastSocket";
try {
InetAddress group = InetAddress.getByName(host);
MulticastSocket s = new MulticastSocket();
//加入多播组
s.joinGroup(group);
DatagramPacket dp = new DatagramPacket(message.getBytes(),message.length(),group,port);
s.send(dp);
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}