IP 多播發(fā)現(xiàn) 就每個(gè)對(duì)等點(diǎn)維護(hù)自己的目錄這點(diǎn)而言,多播模型類似于網(wǎng)絡(luò)模型。但是,對(duì)等點(diǎn)不通過合作來實(shí)現(xiàn)大規(guī)模網(wǎng)絡(luò)查詢。另外,對(duì)等點(diǎn)利用網(wǎng)絡(luò)本身提供的特性(IP 多播)來定位和標(biāo)識(shí)其它對(duì)等點(diǎn)。
IP 多播是無連接和不可靠的(不象 TCP/IP 是面向連接和可靠的)。雖然它使用 IP 數(shù)據(jù)報(bào);但是不象單播 IP 數(shù)據(jù)報(bào)那樣是從一臺(tái)主機(jī)發(fā)送到另一臺(tái)主機(jī),多播 IP 數(shù)據(jù)報(bào)可以同時(shí)發(fā)往多臺(tái)主機(jī)。
對(duì)等點(diǎn)定期使用 IP 多播來公布自己的存在。公布包含了它們的主機(jī)名和一個(gè)用于正常通信的端口。對(duì)此消息感愛好的對(duì)等點(diǎn)檢測(cè)這個(gè)消息后,抽取出主機(jī)名和端口號(hào),并使用該消息建立一個(gè)通信通道。
回顧已經(jīng)足夠了。讓我們開始研究代碼吧。
簡(jiǎn)單的客戶機(jī)與服務(wù)器 我們將從一個(gè)簡(jiǎn)單的示例開始,該示例演示了兩個(gè)進(jìn)程如何使用 IP 多播進(jìn)行通信。為了簡(jiǎn)化演示,我將分別從客戶機(jī)和服務(wù)器進(jìn)程這兩個(gè)方面來介紹示例。P2P 應(yīng)用程序通常會(huì)實(shí)現(xiàn)這兩個(gè)進(jìn)程,將它們劃分為客戶機(jī)或服務(wù)器并不輕易。
清單 1. 簡(jiǎn)單服務(wù)器 public class Server { public static void main(String [] arstring) { try { // Create a multicast datagram socket for receiving IP // multicast packets. Join the multicast group at // 230.0.0.1, port 7777. MulticastSocket multicastSocket = new MulticastSocket(7777); InetAddress inetAddress = InetAddress.getByName("230.0.0.1"); multicastSocket.joinGroup(inetAddress); // Loop forever and receive messages from clients. PRint // the received messages. while (true) { byte [] arb = new byte [100]; DatagramPacket datagramPacket = new DatagramPacket(arb, arb.length); multicastSocket.receive(datagramPacket); System.out.println(new String(arb)); } } catch (Exception exception) { exception.printStackTrace(); } } }
清單 2. 簡(jiǎn)單客戶機(jī) public class Client { public static void main(String [] arstring) { try { // Create a datagram package and send it to the multicast // group at 230.0.0.1, port 7777. byte [] arb = new byte [] {'h','e','l','l','o'}; InetAddress inetAddress = InetAddress.getByName("230.0.0.1"); DatagramPacket datagramPacket = new DatagramPacket(arb, arb.length, inetAddress, 7777); MulticastSocket multicastSocket = new MulticastSocket(); multicastSocket.send(datagramPacket); } catch (Exception exception) { exception.printStackTrace(); } } }
java.net 包中的兩個(gè)類使它運(yùn)行。java.net.DatagramPacket 類保存了 IP 數(shù)據(jù)報(bào)包中包含的數(shù)據(jù)。java.net.MulticastSocket 類創(chuàng)建一個(gè)調(diào)整到一個(gè)特定多播組的多播套接字。
發(fā)現(xiàn)組件 盡管上述示例是一個(gè)很好的 IP 多播的演示,但它沒有說明實(shí)現(xiàn)基于 IP 多播的對(duì)等點(diǎn)發(fā)現(xiàn)需要什么。要使它有用,我們需要一個(gè)功能不僅限于發(fā)送和接收包的軟件組件。理想情況下,這個(gè)組件將了解它所接收的包的源對(duì)等點(diǎn),并適當(dāng)?shù)貋G棄一些信息,這些信息是關(guān)于那些它認(rèn)為已經(jīng)消失、死亡或以其它方式離去的對(duì)等點(diǎn)的。
Member 類 上面描述的框架的完整源代碼太長(zhǎng)了,這里就不具體展示了,所以讓我們只研究 Member 類的部分代碼,因?yàn)槠渲邪瞬僮鞯拇蠖鄶?shù)內(nèi)容。更準(zhǔn)確地說,操作發(fā)生在兩個(gè)內(nèi)部類中:MemberClient 類和 MemberServer 類。
請(qǐng)?jiān)俅慰紤]第一個(gè)示例。它由一個(gè)發(fā)送 IP 多播數(shù)據(jù)報(bào)的客戶機(jī)和一個(gè)接收數(shù)據(jù)報(bào)的服務(wù)器組成。在本例中(清單 3 和 4),兩個(gè)單獨(dú)的應(yīng)用程序執(zhí)行這兩項(xiàng)功能。P2P 應(yīng)用程序中的對(duì)等點(diǎn)的行為方式既象客戶機(jī)又象服務(wù)器,所以我們的 P2P 應(yīng)用程序應(yīng)該同時(shí)包含兩者才是適合的。
清單 3. MemberClient 類 private class MemberClient extends Thread { public void run() { try { while (true) { try { Message message = m_messagefactory.createSendMessage(); Reference reference = message.createReferen