1 多播简介
1.1 IP多播基本概念
1988年Steve Deering 博士论文首次提出,1992年3月IETF在互联网范围内首次试验。多播需要信息由一个源点发送到多个终点,即一对多的通信。
优点是可以节约许多网络资源。举个例子,如果一台视频服务器单播向10太主机发送相同的视频节目,为此,需要发送10个单播,即一个视频分组要发送10个信息副本。而使用多播,视频服务器只需要发送一次。经过路由器时,路由器会自动生成副本发送到目的主机。
1.2多播地址
在互联网上进行多播就叫做IP多播,IP多播所传送的分组需要用到多播IP地址。
IPV4 :D类地址被用于多播(一对多通信),前四位固定为1110。地址范围是224.0.0.0-239.255.255.255。
多播数据报也是“尽最大努力交付”,不保证一定能够交付多播组内地址,并且首部中的协议字段是2,表明使用网际组管理协议IGMP。此外IP多播分为两种,一种是只在本地局域网上进行硬件多播,另一种是在互联网的范围进行多播。
2 Java实现多点广播
2.1 MulticastSocket类
MulticastSocket可以将数据报以广播的方式发送到多个客户端。若要使用多点广播,则需要让一个数据报表有一组目标主机地址,当数据包发出去后,整个组的所有主机都能收到该数据报。这样的组其实就是一个多播地址,当客户端需要发送接受广播信息时加入到该组即可。
MulticastSocket有点像DatagramSocket,事实上MulticastSocket是DatagramSocket的子类,也就是说MulticastSocket是特殊的DatagramSocket。
2.2 MulticastSocket相关用法
构造器 | 说明 |
---|---|
MulticastSocket() | 使用本机默认地址,随机端口来创建对象 |
MulticastSocket(int ports) | 使用默认地址,指定端口来创建对象 |
MulticastSocket(SocketAddress ads) | 指定IP和端口号来创建对象 |
SocketAddress对象封装了一个InetAddress对象和一个代表端口号的整数。即可同时代表IP地址和端口号。
创建MulticastSocket对象后还需要将该MulticastSocket对象加入到指定的多点广播地址,可以调用jionGroup()方法加入指定组。调用leaveGroup()离开一个组。
常用方法 | 说明 | 常用方法 | 说明 |
---|---|---|---|
joinGroup(InetAddress multicastAds) | 加入指定组 | leaveGroup(InetAddress multicastAds) | 离开指定组 |
setInterface() | 设置指定的网络接口 | getInterface() | 查询MulticastSocket监听的网络接口 |
setTimeToLive(int ttl) | ttl取值范围0-255 | setLoopbackMode(boolean flag) | 发送的数据是否送回自身 |
ttl为0时,指定数据包停留在本机;ttl为1时,指定数据报发送到本地局域网;ttl为32时,指定数据报发送到本站点的网络上;ttl为64时,指定数据报应保留在本地区域;ttl为128时,指定数据报保留在本大洲;ttl为255时,指定数据报可以发送任何地方;默认情况下ttl为1。
3 MultcastSocket应用
public class ServerTest_3 implements Runnable{
MulticastSocket socket = null;
byte[] recb = new byte[4096];
DatagramPacket rec = new DatagramPacket(recb, recb.length);
DatagramPacket sed = null;
InetAddress broad = null;
Scanner sc = null;
public void test() throws IOException {
socket = new MulticastSocket(16888);
broad = InetAddress.getByName("230.0.0.1");
socket.joinGroup(broad);
//信息送回自身
socket.setLoopbackMode(false);
//初始化发送包
sed = new DatagramPacket(new byte[0], 0, broad, 16888);
new Thread(this).start();
sc = new Scanner(System.in);
//键盘输入发送消息
while(sc.hasNextLine()) {
byte[] sedb = sc.nextLine().getBytes();
sed.setData(sedb);
socket.send(sed);
}
}
//接受广播信息
@Override
public void run() {
while(true) {
try {
socket.receive(rec);
//将byte数组转换成Sting类型,并且打印
System.out.println(new String(recb, 0, rec.getLength()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
new ServerTest_3().test();
}
}