Member 类
上面描述的框架的完整源代码太长了,这里就不详细展示了,所以让我们只研究 Member 类的部分代码,因为其中包含了操作的大多数内容。更准确地说,操作发生在两个内部类中:MemberClient 类和 MemberServer 类。
请再次考虑第一个示例。它由一个发送 IP 多播数据报的客户机和一个接收数据报的服务器组成。在本例中(清单 3 和 4),两个单独的应用程序执行这两项功能。P2P 应用程序中的对等点的行为方式既象客户机又象服务器,所以我们的 P2P 应用程序应该同时包含两者才是适合的。
清单 3. MemberClient 类
private class MemberClient extends Thread { public void run() { try { while (true) { try { Message message = m_messagefactory.createSendMessage(); Reference reference = message.createReference(); message.writeReference(reference); message.sync(); byte [] arb = message.getByteArray(); DatagramPacket datagrampacket = new DatagramPacket(arb, arb.length); datagrampacket.setAddress(m_inetAddress); datagrampacket.setPort(m_nPort); MulticastSocket multicastsocket = new MulticastSocket(); multicastsocket.send(datagrampacket); } catch (IOException ioException) { ioException.printStackTrace(); } try { synchronized (this) { wait(m_nPeriod); } } catch (InterruptedException interruptedException) { break; } } } catch (Throwable throwable) { throwable.printStackTrace(); } } } |
清单 3 包含了 MemberClient 类的源代码。象清单 1 中的客户机一样,这个客户机创建一个 MulticastSocket 实例并使用它来发送一个 DatagramPacket 实例。DatagramPacket 实例包含一个到发送方对等点的引用,该引用是作为字节数组编码的。只要该对等点还是活动的并在运行,客户机就会每隔一段常规时间来广播这条信息。
清单 4. MemberServer 类
private class MemberServer extends Thread { public void run() { try { MulticastSocket multicastsocket = new MulticastSocket(m_nPort); multicastsocket.joinGroup(m_inetAddress); while (true) { Message message = m_messagefactory.createReceiveMessage(); byte [] arb = message.getByteArray(); DatagramPacket datagrampacket = new DatagramPacket(arb, arb.length); multicastsocket.receive(datagrampacket); message.sync(); if (m_messagefactory.isMine(message) == false) { Reference reference = message.createReference(); message.readReference(reference); m_membermanager.addReference(reference); } } } catch (Throwable throwable) { throwable.printStackTrace(); } } } |
MemberServer 类在很多方面类似于清单 2 中的服务器。除了创建必需的代码,使用它从建立的通信(wire)上采集适当的数据报以外,这个服务器还对已编码的引用进行解码、创建消息并将消息传递到 MemberManager 实例进行保管。干得不错。
该类的其余部分由用于各种特性的读方法和写方法以及用于控制该类的生命周期的 start()和 stop()方法组成。
P2P 应用程序
对等点发现框架完成了,剩下的所有工作就是将它集成到现有的 P2P 应用程序中去了。对原来的 P2P 应用程序的更改相对较少。
首先,在其前身中,P2P 应用程序期望在其特性文件中列出所有已知的对等点。尽管这对演示用途来说很好(请回忆上面讨论的点到点配置),并在最多至大约四个对等点的情况下运行良好,但最终它的限制还是太大了。因此,除去了在特性文件中读取和管理对等点的代码,并以使用上面的发现机制的代码取代它。
其次,因为在特性文件中枚举了对等点,看上去它们就好象持久存在了。现有的应用程序如果假定它们不会消失,有时会侥幸获得成功。但是,在P2P的真实世界中,事情更易发生变化。新的应用程序进行了重新设计,适于在对等点消失时进行更好的恢复。
更新的源代码可在参考资料中得到。
结束语
找到对等点只是成功了一半。下一次我将研究一个难题,涉及两个对等点在现代因特网上的通信,要克服防火墙、网关以及其它一大堆麻烦。