JAVA网络编程-IP组播
组播
组播地址和组
路由器和路由
使用组播Socket
前面几章的Socket都是单播Socket,它们提供点对点的通讯。单播Socket在两个明确的端点之间创建一个连接,有一个是发送方和一个接收方,虽然它们可能互相交换角色,但是任何指定时刻很容易区别谁是谁。不过尽管点对点的通信有很多用途,但如果不是非常需要很多任务需要另一种不同的通讯模型。例如,电视台要从一个位置将数据广播到其他发送范围内的每个点。
组播
组播比单播的点对点通信宽,组播将数据从一个主机发送给不同的主机,但不是发送给每一个人,数据只传送到加入某个特定的组播组中。组播设计为尽可能无缝于Internet。大多数工作都是由路由器完成,对于应用程序员来说是相当透明的。应用程序只是将数据包发送给一个组播地址,它的功能于任何其他的IP地址并没有区别。路由器将确保包被分发到该组播中的所有主机。至于应用本身,需要注意数据包中称为生存时间(TTL)值的附加首部字段。TTL是允许数据包经过的最大路由器数目,当达到这个最大值时,即如果数据包已经过了这么多路由器,就会将这个包丢弃。组播使用TTL作为一种专门方法来限制包可以传输多元。
组播地址和组
组播地址是称为组播组的一组主机的共享地址。IPv4组播地址的范围是224.0.0.0到239.255.255.255之间。IPv6组播地址是ff00::/8中的IP地址,即它们都是以字节0xFF开始,或者二进制表示为11111111.组播是一组共享一个组播地址的Internet主机。任何发送给该组播地址的数据都会中继发送给组中的所有成员。组播中的成员是开放的,主机可以在任何时候进入或离开组。组可以是永久的,也可以是临时的。要创建一个新的组播组,所要做的就是在225.0.0.0到238.255.255.255之间随机选择一个地址,为该地址构造一个InetAddress对象,开始向它发送数据。
路由器和路由
如果没有组播Socket,服务器就必须向路由器发出N个单独但相同的数据流,路由器将每个流路由到客户端,使用同一个流向多个客户端发送相同的数据大大降低了Internet主干网所需的带宽。使用组播Socket通过向Internet向客户端的路由器发送一个数据流,这个路由器复制数据流,并发送到每个客户端。
使用组播Socket
MulticastSender类使用MulticastSocket创建一个组播Socket,使用joinGroup将自身绑定到224.0.0.0的组播地址中,然后循环发送三次数据,发送数据依然使用send()方法。send()方法接收DatagramPacket就是UDP使用的那个DatagramPacket,将数据组播到端口255上。
MulticastSniffer2和MulticastSniffer2两个类同样绑定到224.0.0.0组播中,监听255端口,不断地调用receive()接收数据。
public class MulticastSniffer { public static void main(String[] args) throws Exception { MulticastSocket ms = new MulticastSocket(255); ms.joinGroup(InetAddress.getByName("224.0.0.0")); while (true) { DatagramPacket dp = new DatagramPacket(new byte[10], 10); ms.receive(dp); System.out.println(new String(dp.getData(), 0, dp.getLength())); } } }
public class MulticastSniffer2 { public static void main(String[] args) throws Exception { MulticastSocket ms = new MulticastSocket(255); ms.joinGroup(InetAddress.getByName("224.0.0.0")); while (true) { DatagramPacket dp = new DatagramPacket(new byte[10], 10); ms.receive(dp); System.out.println(new String(dp.getData(), 0, dp.getLength())); } } }
public class MulticastSender { public static void main(String[] args) throws Exception{ MulticastSocket ms = new MulticastSocket(); InetAddress ia = InetAddress.getByName("224.0.0.0"); int port = 255; ms.joinGroup(ia);byte [] body = "12345".getBytes(); for (int i=0;i<3;i++){ ms.send(new DatagramPacket(body,body.length,ia,port)); } } }