java中应用多播技术
最近看了许多java分布式方面书籍,在这里总结一下,介绍分布式应用中一项重要技术,多播通信,并提供我写的一个利用多播技术开发的简易聊天室程序。
多播技术:多播技术并不是java创造的,它在互联网协议这一层已经提供了相当多的支持,任何语言都可以访问此服务,不过java语言提供了一个访问此服务的相对简单的而又与平台无关的标准接口。但是,并不像点对点连接中,接收方可以简单的通过要求发送方重发丢失的数据分组,TCP协议就可以容易地纠正诸如丢包这样的小错误,在多点连接中,这些错误中大多数都不能简单的得到修补。如果在很多接收方中的一个测有收到某个数据分组就不能简单地给所有的接收方重发这个包。虽然TCP协议可以提供一个可靠的服务,但在多播这样的场合,它也无能为力。至于IP多播技术虽然也是基于IP协议的,但它使用的是另外一个不同的传输协议,UDP,UDP协议可以发送单个的数据分组,我们称为数据报,但它并没有提供任何纠错手段。
多播通信是一类特殊的IP地址(D类IP地址)这些IP地址并不和任何主机关联,而是专门为多播通信保留下来的,这些地址范围在224.0.0.1~239.255.255.255这间,其中224.0.0.1~224.0.0.255是留作为多播路由信息使用的。此外,所有其它D类IP地址都可以随便进行通信。
举个例子,互联网上的多媒体会议就是一种多播技术的应用程序。特别是在传输视频数据或是音频数据的场合,偶尔的数据丢失是可以容易克服的,因为这样的场合,当视频数据正在接收端直接播放的时候,后来的数据补足是没有什么用处的。实时通信中经常就是这样的,传输同样的数据到多个接收方,使用多播技术比使用多个点对点连接要更有效率,因为多播技术在一个通信线程上采用广播的方式只发送一次,路由器自身能够决定它们是否需要发送一个多播消息,而关于一个接收方是否登记为一个多播地址这样的信息也可以由路由器去处理,另外,多播消息通常带有一个严格的生存周期,它对应着要通过的路由器数量,例如:如果消息的生存期数据为1,那么这个消息就只能在局域网内部传递,如果这个数值并没有专门的设置,默认是1,因此这样的消息就被限制在局域网内了。
从jdk1.1以后,java.net包中对多播套接字提供了支持,为了给一个多播组发送消息,你必须先为一个合适的端口创建一个多播套接字(MulticastSocket)。
InetAddress group=InetAddress.getByName(“226.1.3.5”);
Int port=6789;
MulticastSocket socket=new MulticastSocket(port);
发送方没有必要一定登记到一个组里去就可以简单地往多播地址发送数据,为了做到这一点,它会创建一个DatagramPacket对像,把它赋给一个数据缓存,并使用字节数组来填充后通过准备好的套接字发送出去。
Byte[] buffer= new byte[500];
DatagramPacket datagram=new DatagramPacket(buffer,buffer.length,group,port);
Datagram.setData(new String(“hello world”).getBytes());
socket.send(datagram);
为了接收数据不完全统计报,接收方必须将自己登记到一个组里,这可以通过使用发送方指定端口号来创建MulticastSocket,然后再调用joinGroup()方法将自己加到这个组里完成登记。
int port=6789;
MulticastSocket socket=new MulticastSocket(port);
InetAddress group=InetAddress.getByName(“226.1.3.5”);
socket.joinGroup(group);
接着,接收方就可以等待数据的到来了,实际上,为了不至于阻塞现有应用,这种情况通常需要创建一个专门的线程做无限循环等待,消息是通过字节流传送过来的,为了能够解释数据报中的信息,接收方必须知道要到来的信息数据结构,也就是说,它必须能够从字节流中使用解释过程来重建和发送方一样的数据结构。
while(true){
socket.receive(datagram);
String message=new String(datagram.getData());
System.out.println(“Datagram received from”+datagram.getAddress().getHostAddress()+”saying:”+message);
}
使用多播技术的聊天室代码:
一点说明,使用IP多播技术不需要一个负责收转消息的服务器,所以只需要一个客户端就可以了。
import java.net.*;
import java.io.*;
public class ChatClient{
//gui
//ChatFrame gui;
//name
String name;
InetAddress group;
MulticastSocket socket;
//设置端口
int port=6789;
//构造函数
public ChatClient(String name){
this.name=name;
try{
socket=new MulticastSocket(port);
group=InetAddress.getByName("226.1.3.5");
socket.joinGroup(group);
System.out.println("Connected ....../n");
while(true){
byte[] buffer=new byte[1000];
DatagramPacket datagram=new DatagramPacket(buffer,buffer.length);
socket.receive(datagram);
String message=new String(datagram.getData());
System.out.println(message);
}
}catch(Exception e){
System.out.println(e);
}
}
public void sendTextToChat(String message){
message=name+":"+message+"/n";
byte[] buf=(message).getBytes();
DatagramPacket dg=new DatagramPacket(buf,buf.length);
try{
socket.send(dg);
}catch(Exception e){
System.out.println(e);
}
}
public void disconnect(){}
public static void main(String args[]){
if(args.length!=1)
throw new RuntimeException("Syntax:java ChatClient
ChatClient client=new ChatClient(args[0]);
}
}