4 组播套接字
在Java中,可以用java.net.MulticastSocket类组播数据。组播套接字是DatagramSocket的子类,定义如下:
public class MulticastSocket extends DatagramSocket
构造方法有两个:
public MulticastSocket ( ) throws SocketException
public MulticastSocket (int port ) throws SocketException
以上两个方法都是创建组播套接字,第一个方法没有端口号,第二个指定了端口号。
常用的方法如下:
public void joinGroup(InetAddress address) throws IOException
建立了MulticastSocket对象后,为了发送或者接收组播包,必须用joinGroup方法加入一个组播组。若加入的不是组播地址将触发IOException异常。
public void leaveGroup(InetAddress address)throws IOException
如果不想接收组播包了,就调用leaveGroup方法。程序就发信息到组播路由器,通知它向此用户发送数据。若想离开的地址不是组播地址就触发IOException异常。
public void send(DatagramPacket packet, byte, ttl) throws IOExceptin
发送组播包的方法与DatagramSocket发送数据相似。其中ttl是生存时间,大小在0~255之间。
public void receive(DatagramPacket p) 与DatagramSocket的接收方法没有差别。
public void setTimeToLive(int ttl )throws IOException 设置套接字发出的组播包中的默认ttl数值。
public int getTimeToLive( ) throws IOException 返回ttl数值。
使用组播套接字发送数据的过程是首先用MulticastSocket()构造器创建MulticastSocket类,然后利用MulticastSocket类的joinGroup()方法加入一个组播组,之后创建DatagramPacket数据包,最后调用MulticastSocket类的send()方法发送组播包。
发送组播包的代码如下:
try {
InetAddress address = InetAddress.getByName (www.mmm.net) ;
byte[ ] data=" java networking";
int port =5000;
DatagramPacket datap =new DatagramSocket
(data ,data.length( ),address,port);
MulticastSocket muls =new MulticastSocket ( );
muls.send(datap );
}
catch(IOException ie) {
} |
使用组播套接字接收数据的过程是首先用MulticastSocket()构造器创建MulticastSocket类,然后利用MulticastSocket类的joinGroup()方法加入一个组播组,之后用receive()方法接收组播包。我们发现其过程与UDP包的过程很相似,区别是要加入一个组播组。
5 实例:组播套接字C/S程序
下面的程序示例12-12说明了组播套接字的基本用法。
【程序源代码】
1 // ==================== Program Description =====================
2 // 程序名称:示例12-12: MulticastServer.java
3 // 程序目的:创建一个组播服务器
4 //==========================================================
5 import java.io.*;
6 import java.net.*;
7 import java.util.*;
8
9 class QuoteServerThread extends Thread
10 {
11 protected DatagramSocket socket = null;
12 protected BufferedReader in = null;
13 protected boolean moreQuotes = true;
14
15 public QuoteServerThread() throws IOException {
16 this("QuoteServerThread");
17 }
18
19 public QuoteServerThread(String name) throws IOException {
20 super(name);
21 socket = new DatagramSocket(4445);
22
23 try {
24 in = new BufferedReader(new FileReader("one-liners.txt"));
25 } catch (FileNotFoundException e) {
26 System.err.println("Could not open quote file.
Serving time instead.");
27 }
28 }
29
30 public void run() {
31 while (moreQuotes) {
32 try {
33 byte[] buf = new byte[256];
34
35 // 获取请求
36 DatagramPacket packet = new DatagramPacket(buf, buf.length);
37 socket.receive(packet);
38
39 // 进行响应
40 String dString = null;
41 if (in == null)
42 dString = new Date().toString();
43 else
44 dString = getNextQuote();
45 buf = dString.getBytes();
46
47 // 向用户发送响应
48 InetAddress address = packet.getAddress();
49 int port = packet.getPort();
50 packet = new DatagramPacket(buf, buf.length, address, port);
51 socket.send(packet);
52 }
53 catch (IOException e) {
54 e.printStackTrace();
55 moreQuotes = false;
56 }
57 }
58 socket.close();
59 }
60
61 protected String getNextQuote() {
62 String returnValue = null;
63 try {
64 if ((returnValue = in.readLine()) == null) {
65 in.close();
66 moreQuotes = false;
67 returnValue = "No more quotes. Goodbye.";
68 }
69 } catch (IOException e) {
70 returnValue = "IOException occurred in server.";
71 }
72 return returnValue;
73 }
74 }
75
76 class MulticastServerThread extends QuoteServerThread
77 {
78 private long FIVE_SECONDS = 5000;
79
80 public MulticastServerThread() throws IOException {
81 super("MulticastServerThread");
82 }
83
84 public void run() {
85 while (moreQuotes) {
86 try {
87 byte[] buf = new byte[256];
88
89 // 构造引用
90 String dString = null;
91 if (in == null)
92 dString = new Date().toString();
93 else
94 dString = getNextQuote();
95 buf = dString.getBytes();
96
97 // 发送
98 InetAddress group = InetAddress.getByName("136.122.133.1");
99 DatagramPacket packet =new
DatagramPacket(buf,buf.length,group,
100 4446);
101 socket.send(packet);
102
103 // 休眠
104 try {
105 sleep((long)(Math.random() * FIVE_SECONDS));
106 }
107 catch (InterruptedException e) { }
108 }
109 catch (IOException e) {
110 e.printStackTrace();
111 moreQuotes = false;
112 }
113 }
114 socket.close();
115 }
116 }
117
118 public class MulticastServer {
119 public static void main(String[] args) throws java.io.IOException {
120 new MulticastServerThread().start();
121 }
122 } |
【程序注解】
服务器程序由3个类组成:QuoteServerThread,MulticastServerThread和MulticastServer。它们的关系是:QuoteServerThread继承自线程类,而MulticastServerThread类继承自类QuoteServerThread。这个程序主要的部分在QuoteServerThread和MulticastServerThread。QuoteServerThread类有两个构造函数,其中在构造函数QuoteServerThread(String name)中,初始化了DatagramSocket套接字并打开了文件one-liners.txt,在这个文件中存有服务器发送的字符串。
在QuoteServerThread类的run()函数中,服务器端套接字接收来自客户端的数据包,并从文件中读取数据,把信息发给客户端。
MulticastServerThread类中重载了run( )方法,实现的功能基本相同,在发完服务器的信息后,用sleep( )函数停止处理了一个随机的时间。
在MultiServer类中,用 new MulticastServerThread().start()开始服务器线程。我们现在只是关注其基本思想。
示例12-13是UDP组播的客户端程序。
【程序源代码】
1 // ==================== Program Description =====================
2 // 程序名称:示例12-13: MulticastClient.java
3 // 程序目的:UDP组播客户端
4 //====================>7??:示例1D====================================
5 import java.io.*;
6 import java.net.*;
7 import java.util.*;
8
9 public class MulticastClient
10 {
11 public static void main(String[] args) throws IOException
12 {
13 MulticastSocket socket = new MulticastSocket(4446);
14 InetAddress address = InetAddress.getByName("136.122.133.1");
15 socket.joinGroup(address);
16 DatagramPacket packet;
17
18 for (int i = 0; i < 5; i++)
19 {
20 byte[] buf = new byte[256];
21 packet = new DatagramPacket(buf, buf.length);
22 socket.receive(packet);
23 String received = new String(packet.getData());
24 System.out.println("Quote of the Moment: " + received);
25 }
26
27 socket.leaveGroup(address);
28 socket.close();
29 }
30 } |
【程序输出结果】
Quote of the Moment: Give me ambiguity or give me something else.
Quote of the ME7??:示例1oment: I.R.S.: We've got what it takes to take what you've got!
Quote of the Moment: We are born naked, wet and hungry. Then things get worse.
Quote of the Moment: Make it idiot proof and someone will make a better idiot.
Quote of the Moment: He who laughs last thinks slowest!
【程序注解】
在客户端的main()方法中,第13行实例化了一个MulticastSocket对象socket,然后用join()方法加入了组播组136.122.133.1。在for循环中接收了5个数据包,并把数据包中的内容显示出来(第18~25行)。最后在第27行离开组播组(leaveGroup)。