繼續看 Oracle 的範例程式,在裡面舉出 UDP 最重要的運用 -- 群播,之前兩個範例程式測試的方式都是先執行 server,再執行 client,這個群播程式要反過來,先執行 client 以等待 server 廣播出來的訊息。
1 package idv.steven; 2 3 import java.io.IOException; 4 5 public class MulticastServer { 6 public static void main(String[] args) throws IOException { 7 new MulticastServerThread().start(); 8 } 9 }
1 package idv.steven; 2 3 import java.io.*; 4 import java.net.*; 5 import java.util.*; 6 7 public class MulticastServerThread extends QuoteServerThread { 8 9 private long FIVE_SECONDS = 5000; 10 11 public MulticastServerThread() throws IOException { 12 super("MulticastServerThread"); 13 } 14 15 public void run() { 16 while (moreQuotes) { 17 try { 18 byte[] buf = new byte[256]; 19 20 // construct quote 21 String dString = null; 22 if (in == null) 23 dString = new Date().toString(); 24 else 25 dString = getNextQuote(); 26 buf = dString.getBytes(); 27 28 // send it 29 InetAddress group = InetAddress.getByName("230.0.0.1"); 30 DatagramPacket packet = new DatagramPacket(buf, buf.length, group, 4446); 31 socket.send(packet); 32 33 // sleep for a while 34 try { 35 sleep((long)(Math.random() * FIVE_SECONDS)); 36 } catch (InterruptedException e) { 37 38 } 39 } catch (IOException e) { 40 e.printStackTrace(); 41 moreQuotes = false; 42 } 43 } 44 socket.close(); 45 } 46 }
注意看程式第 29 行,裡面有個 IP -- 230.0.0.1,這是做什麼的? 這個值只要是 UDP 群播的合理 IP 值就可以了,我們可以任意的選擇,也可以傳入 null 表示將作 loopback。這個值會成為群播的"群組",client 端倒底要傾聽那裡傳來的群播訊息? 即是透過指定群組來決定。程式第 30 行的 4446 這個 port 值也很重要,client 端必須傾聽這個 port 才收的到群播的訊息。程式第 31 行,將訊息廣播出去… 程式第 35 行只是停頓數秒,讓我們查看程式的執行比較方便罷了,整個廣播的過程會持續到所有文字檔內容被讀取並傳送完畢為止。
【註】在 IPv4 裡,224.0.0.1 ~ 239.255.255.255 這個網段是被指定作為 multicast 群組。
1 package idv.steven; 2 3 import java.io.*; 4 import java.net.*; 5 import java.util.*; 6 7 public class MulticastClient { 8 9 public static void main(String[] args) throws IOException { 10 11 MulticastSocket socket = new MulticastSocket(4446); 12 InetAddress address = InetAddress.getByName("230.0.0.1"); 13 socket.joinGroup(address); 14 15 DatagramPacket packet; 16 17 // get a few quotes 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 24 String received = new String(packet.getData(), 0, packet.getLength()); 25 System.out.println("Quote of the Moment: " + received); 26 } 27 28 socket.leaveGroup(address); 29 socket.close(); 30 } 31 }
client 端程式要注意的就是第 11~13 行,指定要傾聽那個群組、那個 port 的訊息,透過呼叫 joinGroup 後加入這個群組,真正開始傾聽是在程式第 22 行。