要完成有用
![](/icons/66345de.gif)
工作
![](/icons/66345dou.gif)
P2P 应用
![](/icons/66345chengxu.gif)
中
![](/icons/66345de.gif)
对等点必须能够彼此发现对方并和对方交互
![](/icons/66345dou2.gif)
在上
![](/icons/66345yi.gif)
篇文章中
![](/icons/66345dou.gif)
Todd 描述了几种区别
![](/icons/66345de.gif)
机制
![](/icons/66345dou.gif)
对等点可以使用这些机制彼此发现
![](/icons/66345dou.gif)
他还解释了每种机制
![](/icons/66345de.gif)
优缺点
![](/icons/66345dou2.gif)
本月
![](/icons/66345dou.gif)
他提供了
![](/icons/66345yi.gif)
种基于 IP 多播
![](/icons/66345de.gif)
发现
![](/icons/66345de.gif)
实现
![](/icons/66345dou2.gif)
在软件Software实体能够参和具有 P2P 应用
![](/icons/66345chengxu.gif)
特征
![](/icons/66345de.gif)
直接
![](/icons/66345de.gif)
对等交互的前
![](/icons/66345dou.gif)
该实体必须发现将要和的交互
![](/icons/66345de.gif)
适当
![](/icons/66345de.gif)
对等点
![](/icons/66345dou2.gif)
所有可行
![](/icons/66345de.gif)
P2P 体系结构都提供
![](/icons/66345yi.gif)
种针对发现问题
![](/icons/66345de.gif)
解决方案
![](/icons/66345dou2.gif)
上
![](/icons/66345yi.gif)
次
![](/icons/66345dou.gif)
我们研究了实现发现
![](/icons/66345de.gif)
几种区别
![](/icons/66345de.gif)
思路方法
![](/icons/66345dou2.gif)
本月
![](/icons/66345dou.gif)
我将描述其中
![](/icons/66345yi.gif)
种机制
![](/icons/66345de.gif)
实现
![](/icons/66345dou2.gif)
让我们通过回顾来开始今天
![](/icons/66345de.gif)
讨论
![](/icons/66345dou2.gif)
再访发现
对等点发现使 P2P 应用
![](/icons/66345chengxu.gif)
中
![](/icons/66345de.gif)
对等点能够彼此定位以便相互的间可以交互
![](/icons/66345dou2.gif)
实现对等点发现服务有多种思路方法
![](/icons/66345dou2.gif)
最简单
![](/icons/66345de.gif)
机制是显式点到点配置
![](/icons/66345dou2.gif)
这种机制通过要求每个对等点知道所有它可能和的交互
![](/icons/66345de.gif)
其它对等点
![](/icons/66345dou.gif)
并和它们相连
![](/icons/66345dou.gif)
来进行工作
![](/icons/66345dou2.gif)
点到点配置
![](/icons/66345de.gif)
主要优点是简单
![](/icons/66345dou2.gif)
它
![](/icons/66345de.gif)
主要缺点是缺乏灵活性并且缺少扩展到对等点
![](/icons/66345de.gif)
大型网络
![](/icons/66345de.gif)
能力
![](/icons/66345dou2.gif)
发现
![](/icons/66345de.gif)
另
![](/icons/66345yi.gif)
个公共模型是使用中央目录作为中介
![](/icons/66345dou2.gif)
该模型在许多传统
![](/icons/66345de.gif)
、非 P2P 分布式类型
![](/icons/66345de.gif)
应用
![](/icons/66345chengxu.gif)
中间很流行
![](/icons/66345dou.gif)
其优点是很好理解
![](/icons/66345dou2.gif)
对等点向中央目录注册自己
![](/icons/66345de.gif)
存在
![](/icons/66345dou.gif)
并使用中央目录定位其它对等点
![](/icons/66345dou2.gif)
这种模型
![](/icons/66345de.gif)
主要优点是易于管理和扩展
![](/icons/66345de.gif)
能力
![](/icons/66345dou2.gif)
但是
![](/icons/66345dou.gif)
其集中化设计会导致单点故障
![](/icons/66345dou.gif)
因此它对自然力或网上冲浪人数增加所带来
![](/icons/66345de.gif)
危害缺乏抵御能力
![](/icons/66345dou2.gif)
许多流行
![](/icons/66345de.gif)
P2P 应用
![](/icons/66345chengxu.gif)
使用网络模型而不是中央目录
![](/icons/66345dou.gif)
在网络模型中
![](/icons/66345dou.gif)
单个对等点只知道局域网络上
![](/icons/66345de.gif)
对等点身份
![](/icons/66345dou2.gif)
每个对等点都作为那些和的相连
![](/icons/66345de.gif)
对等点
![](/icons/66345de.gif)
目录
![](/icons/66345dou2.gif)
对等点通过向相邻对等点传播目录查询并返回相关
![](/icons/66345de.gif)
响应来进行合作
![](/icons/66345dou2.gif)
这种模型
![](/icons/66345de.gif)
主要优点是没有集中化
![](/icons/66345dou2.gif)
它
![](/icons/66345de.gif)
主要缺点是由于传播查询耗费了大量
![](/icons/66345de.gif)
网络和处理能力
![](/icons/66345dou2.gif)
上面 3种机制有无数种变体
![](/icons/66345dou2.gif)
不讨论这些变体了
![](/icons/66345dou.gif)
让我们继续前进并研究另
![](/icons/66345yi.gif)
种发现机制
![](/icons/66345dou2.gif)
IP 多播发现
就每个对等点维护自己
![](/icons/66345de.gif)
目录这点而言
![](/icons/66345dou.gif)
多播模型类似于网络模型
![](/icons/66345dou2.gif)
但是
![](/icons/66345dou.gif)
对等点不通过合作来实现大规模网络查询
![](/icons/66345dou2.gif)
另外
![](/icons/66345dou.gif)
对等点利用网络本身提供
![](/icons/66345de.gif)
特性(IP 多播)来定位和标识其它对等点
![](/icons/66345dou2.gif)
IP 多播是无连接和不可靠
![](/icons/66345de.gif)
(不象 TCP/IP 是面向连接和可靠
![](/icons/66345de.gif)
)
![](/icons/66345dou2.gif)
虽然它使用 IP 数据报;但是不象单播 IP 数据报那样是从
![](/icons/66345yi.gif)
台主机发送到另
![](/icons/66345yi.gif)
台主机
![](/icons/66345dou.gif)
多播 IP 数据报可以同时发往多台主机
![](/icons/66345dou2.gif)
对等点定期使用 IP 多播来宣布自己
![](/icons/66345de.gif)
存在
![](/icons/66345dou2.gif)
宣布包含了它们
![](/icons/66345de.gif)
主机名和
![](/icons/66345yi.gif)
个用于正常通信
![](/icons/66345de.gif)
端口
![](/icons/66345dou2.gif)
对此消息感兴趣
![](/icons/66345de.gif)
对等点检测这个消息后
![](/icons/66345dou.gif)
抽取出主机名和端口号
![](/icons/66345dou.gif)
并使用该消息建立
![](/icons/66345yi.gif)
个通信通道
![](/icons/66345dou2.gif)
回顾已经足够了
![](/icons/66345dou2.gif)
让我们开始研究代码吧
![](/icons/66345dou2.gif)
简单
![](/icons/66345de.gif)
客户机和服务器
我们将从
![](/icons/66345yi.gif)
个简单
![](/icons/66345de.gif)
举例开始
![](/icons/66345dou.gif)
该举例演示了两个进程如何使用 IP 多播进行通信
![](/icons/66345dou2.gif)
为了简化演示
![](/icons/66345dou.gif)
我将分别从客户机和服务器进程这两个方面来介绍举例
![](/icons/66345dou2.gif)
P2P 应用
![](/icons/66345chengxu.gif)
通常会实现这两个进程
![](/icons/66345dou.gif)
将它们划分为客户机或服务器并不容易
![](/icons/66345dou2.gif)
在本例中
![](/icons/66345dou.gif)
服务器进程进行循环并等待数据报包
![](/icons/66345de.gif)
到来
![](/icons/66345dou2.gif)
每接收到
![](/icons/66345yi.gif)
个包
![](/icons/66345dou.gif)
服务器就会向控制台打印
![](/icons/66345yi.gif)
条简短
![](/icons/66345de.gif)
诊断消息
![](/icons/66345dou2.gif)
客户机角色要简单得多 — 它多播单个数据报包并退出
![](/icons/66345dou2.gif)
清单 1 和 2 介绍说明了这两部分是如何组合在
![](/icons/66345yi.gif)
起
![](/icons/66345de.gif)
![](/icons/66345dou2.gif)
代码中
![](/icons/66345de.gif)
注释介绍说明了正在发生
![](/icons/66345de.gif)
事情
![](/icons/66345dou2.gif)
清单 1. 简单服务器
public
![](/icons/66345class.gif)
Server
{
public
![](/icons/66345static.gif)
void
![](/icons/66345main.gif)
(String
![](/icons/66345zhk2.gif)
ar
![](/icons/66345string.gif)
)
{
try
{
// Create a multicast datagram
![](/icons/66345socket.gif)
for receiving IP
// multicast packets. Join the multicast group at
// 230.0.0.1, port 7777.
MulticastSocket multicastSocket =
![](/icons/66345new.gif)
MulticastSocket(7777);
InetAddress inetAddress = InetAddress.getByName("230.0.0.1");
multicastSocket.joinGroup(inetAddress);
// Loop forever and receive messages from clients. Pr
![](/icons/66345int.gif)
// the received messages.
while (true)
{
![](/icons/66345zhk2.gif)
arb =
![](/icons/66345byte.gif)
[100];
DatagramPacket datagramPacket =
![](/icons/66345new.gif)
DatagramPacket(arb, arb.length);
multicastSocket.receive(datagramPacket);
![](/icons/66345System.gif)
.out.pr
![](/icons/66345int.gif)
ln(
![](/icons/66345new.gif)
String(arb));
}
}
catch (Exception exception)
{
exception.pr
![](/icons/66345int.gif)
StackTrace
![](/icons/66345kh.gif)
;
}
}
}
清单 2. 简单客户机
public
![](/icons/66345class.gif)
Client
{
public
![](/icons/66345static.gif)
void
![](/icons/66345main.gif)
(String
![](/icons/66345zhk2.gif)
ar
![](/icons/66345string.gif)
)
{
try
{
// Create a datagram package and send it to the multicast
// group at 230.0.0.1, port 7777.
![](/icons/66345zhk2.gif)
arb =
![](/icons/66345zhk2.gif)
{'h','e','l','l','o'};
InetAddress inetAddress = InetAddress.getByName("230.0.0.1");
DatagramPacket datagramPacket =
![](/icons/66345new.gif)
DatagramPacket(arb, arb.length, inetAddress, 7777);
MulticastSocket multicastSocket =
![](/icons/66345new.gif)
MulticastSocket
![](/icons/66345kh.gif)
;
multicastSocket.send(datagramPacket);
}
catch (Exception exception)
{
exception.pr
![](/icons/66345int.gif)
StackTrace
![](/icons/66345kh.gif)
;
}
}
}
java.net 包中
![](/icons/66345de.gif)
两个类使它运行
![](/icons/66345dou2.gif)
java.net.DatagramPacket 类保存了 IP 数据报包中包含
![](/icons/66345de.gif)
数据
![](/icons/66345dou2.gif)
java.net.MulticastSocket 类创建
![](/icons/66345yi.gif)
个调整到
![](/icons/66345yi.gif)
个特定多播组
![](/icons/66345de.gif)
多播套接字
![](/icons/66345dou2.gif)
发现组件
尽管上述举例是
![](/icons/66345yi.gif)
个很好
![](/icons/66345de.gif)
IP 多播
![](/icons/66345de.gif)
演示
![](/icons/66345dou.gif)
但它没有介绍说明实现基于 IP 多播
![](/icons/66345de.gif)
对等点发现需要什么
![](/icons/66345dou2.gif)
要使它有用
![](/icons/66345dou.gif)
我们需要
![](/icons/66345yi.gif)
个功能不仅限于发送和接收包
![](/icons/66345de.gif)
软件Software组件
![](/icons/66345dou2.gif)
理想情况下
![](/icons/66345dou.gif)
这个组件将了解它所接收
![](/icons/66345de.gif)
包
![](/icons/66345de.gif)
源对等点
![](/icons/66345dou.gif)
并适当地丢弃
![](/icons/66345yi.gif)
些信息
![](/icons/66345dou.gif)
这些信息是有关那些它认为已经消失、死亡或以其它方式离去
![](/icons/66345de.gif)
对等点
![](/icons/66345de.gif)
![](/icons/66345dou2.gif)
在这个新设计中
![](/icons/66345dou.gif)
对等点是
![](/icons/66345yi.gif)
个多播组
![](/icons/66345de.gif)
成员
![](/icons/66345dou2.gif)
请牢记
![](/icons/66345dou.gif)
发送到多播组
![](/icons/66345de.gif)
消息会透明地路由到该组
![](/icons/66345de.gif)
所有成员
![](/icons/66345dou2.gif)
设计包括两个核心类和 3个接口(我使用术语“接口”似乎不太严谨 — 在技术上是
![](/icons/66345yi.gif)
个接口和两个抽象类)
![](/icons/66345dou2.gif)
Member 类
![](/icons/66345de.gif)
例子是
![](/icons/66345yi.gif)
个多播组
![](/icons/66345de.gif)
成员
![](/icons/66345dou2.gif)
这个类管理所有
![](/icons/66345de.gif)
通信细节
![](/icons/66345dou2.gif)
MemberManager 类
![](/icons/66345de.gif)
![](/icons/66345yi.gif)
个例子负责了解参和多播组
![](/icons/66345de.gif)
其它成员
![](/icons/66345dou2.gif)
对等点通过向多播组发送
![](/icons/66345yi.gif)
个消息
![](/icons/66345dou.gif)
来向属于多播组中
![](/icons/66345de.gif)
对等点宣布自己
![](/icons/66345de.gif)
存在
![](/icons/66345dou2.gif)
每个消息包含有关发送消息
![](/icons/66345de.gif)
对等点
![](/icons/66345de.gif)
信息 — 通常是主机名和用于正常(和发现无关)通信
![](/icons/66345de.gif)
端口
![](/icons/66345dou2.gif)
Member 类和 MemberManager 类对这些消息
![](/icons/66345de.gif)
内容几乎
![](/icons/66345yi.gif)
无所知
![](/icons/66345dou2.gif)
对该信息
![](/icons/66345de.gif)
访问权属于使用这两个类
![](/icons/66345de.gif)
应用
![](/icons/66345chengxu.gif)
![](/icons/66345dou2.gif)
有 3个接口跨越了消息传递/发现层和使用它
![](/icons/66345de.gif)
应用
![](/icons/66345chengxu.gif)
层的间
![](/icons/66345de.gif)
边界
![](/icons/66345dou2.gif)
它们是 Reference 抽象类、Message 接口和 MessageFactory 抽象类
![](/icons/66345dou2.gif)
应用
![](/icons/66345chengxu.gif)
必须提供这 3个接口
![](/icons/66345de.gif)
实现
![](/icons/66345dou2.gif)
Reference 抽象类定义了对多播组成员
![](/icons/66345de.gif)
引用
![](/icons/66345dou2.gif)
MemberManager 类管理
![](/icons/66345yi.gif)
个引用集
![](/icons/66345dou2.gif)
应用
![](/icons/66345chengxu.gif)
将实现这个类
![](/icons/66345de.gif)
![](/icons/66345yi.gif)
个具体版本
![](/icons/66345dou.gif)
它将包含应用
![](/icons/66345chengxu.gif)
所需要
![](/icons/66345de.gif)
任何引用逻辑
![](/icons/66345dou2.gif)
该类定义了两个思路方法
![](/icons/66345dou.gif)
名称是 equalsInternal
![](/icons/66345kh.gif)
和 hashCodeInternal
![](/icons/66345kh.gif)
![](/icons/66345dou.gif)
并且重新定义了 equals
![](/icons/66345kh.gif)
和 hashCode
![](/icons/66345kh.gif)
思路方法来
![](/icons/66345diaoyong.gif)
这些思路方法
![](/icons/66345dou2.gif)
它通过这样做来强制实现者为这两个关键功能提供实现 — MemberManager 依赖于它们
![](/icons/66345dou2.gif)
Message 接口定义了通过网络代码交换
![](/icons/66345de.gif)
消息数据
![](/icons/66345de.gif)
应用
![](/icons/66345chengxu.gif)
视图
![](/icons/66345dou2.gif)
应用
![](/icons/66345chengxu.gif)
将该消息看作是相对于应用
![](/icons/66345chengxu.gif)
运行范围
![](/icons/66345de.gif)
高级概念 — 类似于主机名和端口
![](/icons/66345de.gif)
概念
![](/icons/66345dou2.gif)
网络代码希望发送
![](/icons/66345yi.gif)
个由字节组成
![](/icons/66345de.gif)
包
![](/icons/66345dou2.gif)
Message 接口
![](/icons/66345de.gif)
实现定义了如何将这些高级信息和字节相互转换
![](/icons/66345dou2.gif)
引用是信息
![](/icons/66345de.gif)
![](/icons/66345yi.gif)
个关键部分
![](/icons/66345dou.gif)
所有消息都必须包含
![](/icons/66345dou.gif)
因此该接口要求实现提供用于读和写 reference
![](/icons/66345de.gif)
思路方法
![](/icons/66345dou2.gif)
问题
![](/icons/66345de.gif)
最后部分是 MessageFactory 抽象类
![](/icons/66345dou2.gif)
这个类定义了生成新
![](/icons/66345de.gif)
Message 例子
![](/icons/66345de.gif)
机制
![](/icons/66345dou2.gif)
深藏在 Member 类内
![](/icons/66345de.gif)
网络代码使用
![](/icons/66345yi.gif)
个工厂来创建从多播数据报中抽取出
![](/icons/66345de.gif)
数据
![](/icons/66345de.gif)
Message 例子
![](/icons/66345dou2.gif)
每个 MessageFactory 例子拥有
![](/icons/66345yi.gif)
个随机生成
![](/icons/66345de.gif)
身份
![](/icons/66345dou.gif)
它使用这个身份来从接收
![](/icons/66345de.gif)
消息中滤出要发送
![](/icons/66345de.gif)
消息
![](/icons/66345dou2.gif)
总的
![](/icons/66345dou.gif)
这 5个类和接口(Member、MemberManager、Reference、Message 和 MessageFactory)构成了
![](/icons/66345yi.gif)
个用于进行对等点发现
![](/icons/66345de.gif)
简单框架
![](/icons/66345dou2.gif)
当然
![](/icons/66345dou.gif)
还有可以改进
![](/icons/66345de.gif)
空间
![](/icons/66345dou2.gif)
可以很容易地添加
![](/icons/66345yi.gif)
种基于事件
![](/icons/66345de.gif)
机制
![](/icons/66345dou.gif)
用于向感兴趣
![](/icons/66345de.gif)
侦听器通知成员
![](/icons/66345de.gif)
出现或消失
![](/icons/66345dou2.gif)
![](/icons/66345yi.gif)
种用于过滤所接收消息
![](/icons/66345de.gif)
灵活机制将很有用
![](/icons/66345dou.gif)
但其实现却比较困难
![](/icons/66345dou2.gif)
我将这些建议留作读者
![](/icons/66345de.gif)
作业
![](/icons/66345dou2.gif)
Member 类
上面描述
![](/icons/66345de.gif)
框架
![](/icons/66345de.gif)
完整源代码太长了
![](/icons/66345dou.gif)
这里就不详细展示了
![](/icons/66345dou.gif)
所以让我们只研究 Member 类
![](/icons/66345de.gif)
部分代码
![](/icons/66345dou.gif)
![](/icons/66345yinwei.gif)
其中包含了操作
![](/icons/66345de.gif)
大多数内容
![](/icons/66345dou2.gif)
更准确地说
![](/icons/66345dou.gif)
操作发生在两个内部类中:MemberClient 类和 MemberServer 类
![](/icons/66345dou2.gif)
请再次考虑第
![](/icons/66345yi.gif)
个举例
![](/icons/66345dou2.gif)
它由
![](/icons/66345yi.gif)
个发送 IP 多播数据报
![](/icons/66345de.gif)
客户机和
![](/icons/66345yi.gif)
个接收数据报
![](/icons/66345de.gif)
服务器组成
![](/icons/66345dou2.gif)
在本例中(清单 3 和 4)
![](/icons/66345dou.gif)
两个单独
![](/icons/66345de.gif)
应用
![](/icons/66345chengxu.gif)
执行这两项功能
![](/icons/66345dou2.gif)
P2P 应用
![](/icons/66345chengxu.gif)
中
![](/icons/66345de.gif)
对等点
![](/icons/66345de.gif)
行为方式既象客户机又象服务器
![](/icons/66345dou.gif)
所以我们
![](/icons/66345de.gif)
P2P 应用
![](/icons/66345chengxu.gif)
应该同时包含两者才是适合
![](/icons/66345de.gif)
![](/icons/66345dou2.gif)
清单 3. MemberClient 类
private
![](/icons/66345class.gif)
MemberClient
extends Thread
{
public
void
run
![](/icons/66345kh.gif)
{
try
{
while (true)
{
try
{
Message message = m_messagefactory.createSendMessage
![](/icons/66345kh.gif)
;
Reference reference = message.createReference
![](/icons/66345kh.gif)
;
message.writeReference(reference);
message.sync
![](/icons/66345kh.gif)
;
![](/icons/66345zhk2.gif)
arb = message.getByteArray
![](/icons/66345kh.gif)
;
DatagramPacket datagrampacket =
![](/icons/66345new.gif)
DatagramPacket(arb, arb.length);
datagrampacket.
![](/icons/66345set.gif)
Address(m_inetAddress);
datagrampacket.
![](/icons/66345set.gif)
Port(m_nPort);
MulticastSocket multicast
![](/icons/66345socket.gif)
=
![](/icons/66345new.gif)
MulticastSocket
![](/icons/66345kh.gif)
;
multicast
![](/icons/66345socket.gif)
.send(datagrampacket);
}
catch (IOException ioException)
{
ioException.pr
![](/icons/66345int.gif)
StackTrace
![](/icons/66345kh.gif)
;
}
try
{
synchronized (this)
{
wait(m_nPeriod);
}
}
catch (InterruptedException
![](/icons/66345int.gif)
erruptedException)
{
![](/icons/66345break.gif)
;
}
}
}
catch (Throwable throwable)
{
throwable.pr
![](/icons/66345int.gif)
StackTrace
![](/icons/66345kh.gif)
;
}
}
}
清单 3 包含了 MemberClient 类
![](/icons/66345de.gif)
源代码
![](/icons/66345dou2.gif)
象清单 1 中
![](/icons/66345de.gif)
客户机
![](/icons/66345yi.gif)
样
![](/icons/66345dou.gif)
这个客户机创建
![](/icons/66345yi.gif)
个 MulticastSocket 例子并使用它来发送
![](/icons/66345yi.gif)
个 DatagramPacket 例子
![](/icons/66345dou2.gif)
DatagramPacket 例子包含
![](/icons/66345yi.gif)
个到发送方对等点
![](/icons/66345de.gif)
引用
![](/icons/66345dou.gif)
该引用是作为字节
![](/icons/66345shuzu.gif)
编码
![](/icons/66345de.gif)
![](/icons/66345dou2.gif)
只要该对等点还是活动
![](/icons/66345de.gif)
并在运行
![](/icons/66345dou.gif)
客户机就会每隔
![](/icons/66345yi.gif)
段常规时间来广播这条信息
![](/icons/66345dou2.gif)
清单 4. MemberServer 类
private
![](/icons/66345class.gif)
MemberServer
extends Thread
{
public
void
run
![](/icons/66345kh.gif)
{
try
{
MulticastSocket multicast
![](/icons/66345socket.gif)
=
![](/icons/66345new.gif)
MulticastSocket(m_nPort);
multicast
![](/icons/66345socket.gif)
.joinGroup(m_inetAddress);
while (true)
{
Message message = m_messagefactory.createReceiveMessage
![](/icons/66345kh.gif)
;
![](/icons/66345zhk2.gif)
arb = message.getByteArray
![](/icons/66345kh.gif)
;
DatagramPacket datagrampacket =
![](/icons/66345new.gif)
DatagramPacket(arb, arb.length);
multicast
![](/icons/66345socket.gif)
.receive(datagrampacket);
message.sync
![](/icons/66345kh.gif)
;
![](/icons/66345if.gif)
(m_messagefactory.isMine(message)
![](/icons/66345dd.gif)
false)
{
Reference reference = message.createReference
![](/icons/66345kh.gif)
;
message.readReference(reference);
m_membermanager.addReference(reference);
}
}
}
catch (Throwable throwable)
{
throwable.pr
![](/icons/66345int.gif)
StackTrace
![](/icons/66345kh.gif)
;
}
}
}
MemberServer 类在很多方面类似于清单 2 中
![](/icons/66345de.gif)
服务器
![](/icons/66345dou2.gif)
除了创建必需
![](/icons/66345de.gif)
代码
![](/icons/66345dou.gif)
使用它从建立
![](/icons/66345de.gif)
通信(wire)上采集适当
![](/icons/66345de.gif)
数据报以外
![](/icons/66345dou.gif)
这个服务器还对已编码
![](/icons/66345de.gif)
引用进行解码、创建消息并将消息传递到 MemberManager 例子进行保管
![](/icons/66345dou2.gif)
干得不错
![](/icons/66345dou2.gif)
该类
![](/icons/66345de.gif)
其余部分由用于各种特性
![](/icons/66345de.gif)
读思路方法和写思路方法以及用于控制该类
![](/icons/66345de.gif)
生命周期
![](/icons/66345de.gif)
start
![](/icons/66345kh.gif)
和 stop
![](/icons/66345kh.gif)
思路方法组成
![](/icons/66345dou2.gif)
P2P 应用
![](/icons/66345chengxu.gif)
对等点发现框架完成了
![](/icons/66345dou.gif)
剩下
![](/icons/66345de.gif)
所有工作就是将它集成到现有
![](/icons/66345de.gif)
P2P 应用
![](/icons/66345chengxu.gif)
中去了
![](/icons/66345dou2.gif)
对原来
![](/icons/66345de.gif)
P2P 应用
![](/icons/66345chengxu.gif)
![](/icons/66345de.gif)
更改相对较少
![](/icons/66345dou2.gif)
首先
![](/icons/66345dou.gif)
在其前身中
![](/icons/66345dou.gif)
P2P 应用
![](/icons/66345chengxu.gif)
期望在其特性文件中列出所有已知
![](/icons/66345de.gif)
对等点
![](/icons/66345dou2.gif)
尽管这对演示用途来说很好(请回忆上面讨论
![](/icons/66345de.gif)
点到点配置)
![](/icons/66345dou.gif)
并在最多至大约 4个对等点
![](/icons/66345de.gif)
情况下运行良好
![](/icons/66345dou.gif)
但最终它
![](/icons/66345de.gif)
限制还是太大了
![](/icons/66345dou2.gif)
因此
![](/icons/66345dou.gif)
除去了在特性文件中读取和管理对等点
![](/icons/66345de.gif)
代码
![](/icons/66345dou.gif)
并以使用上面
![](/icons/66345de.gif)
发现机制
![](/icons/66345de.gif)
代码取代它
![](/icons/66345dou2.gif)
其次
![](/icons/66345dou.gif)
![](/icons/66345yinwei.gif)
在特性文件中枚举了对等点
![](/icons/66345dou.gif)
看上去它们就好象持久存在了
![](/icons/66345dou2.gif)
现有
![](/icons/66345de.gif)
应用
![](/icons/66345chengxu.gif)
如果假定它们不会消失
![](/icons/66345dou.gif)
有时会侥幸获得成功
![](/icons/66345dou2.gif)
但是
![](/icons/66345dou.gif)
在 P2P
![](/icons/66345de.gif)
真实世界中
![](/icons/66345dou.gif)
事情更易发生变化
![](/icons/66345dou2.gif)
新
![](/icons/66345de.gif)
应用
![](/icons/66345chengxu.gif)
进行了重新设计
![](/icons/66345dou.gif)
适于在对等点消失时进行更好
![](/icons/66345de.gif)
恢复
![](/icons/66345dou2.gif)
更新
![](/icons/66345de.gif)
源代码可在参考资料中得到
![](/icons/66345dou2.gif)
结束语
找到对等点只是成功了
![](/icons/66345yi.gif)
半
![](/icons/66345dou2.gif)
下
![](/icons/66345yi.gif)
次我将研究
![](/icons/66345yi.gif)
个难题
![](/icons/66345dou.gif)
涉及两个对等点在现代因特网上
![](/icons/66345de.gif)
通信
![](/icons/66345dou.gif)
要克服防火墙、网关以及其它
![](/icons/66345yi.gif)
大堆麻烦
![](/icons/66345dou2.gif)
参考资料
下载并更新本文
![](/icons/66345de.gif)
源代码
![](/icons/66345dou2.gif)
“How IP Multicast Works”
![](/icons/66345yi.gif)
文为初学者提供了很棒
![](/icons/66345de.gif)
介绍
![](/icons/66345dou2.gif)
Jxta Discovery Service 使用 IP 多播来定位合适
![](/icons/66345de.gif)
对等点
![](/icons/66345dou2.gif)
在这个有关 Jxta
![](/icons/66345de.gif)
系列文章中
![](/icons/66345dou.gif)
Making P2P
![](/icons/66345int.gif)
eroperable(developerWorks
![](/icons/66345dou.gif)
2001 年 8-9 月)中
![](/icons/66345dou.gif)
Sing Li 提供了
![](/icons/66345yi.gif)
篇有关这种新
![](/icons/66345de.gif)
P2P 技术
![](/icons/66345de.gif)
实用介绍
![](/icons/66345dou.gif)
并演示了如何使用 Jxta 构建 P2P 应用
![](/icons/66345chengxu.gif)
![](/icons/66345dou2.gif)
Vincent Matossian
![](/icons/66345de.gif)
网站WebSite上有
![](/icons/66345yi.gif)
个很棒
![](/icons/66345de.gif)
到高级 P2P 主题
![](/icons/66345de.gif)
链接集
![](/icons/66345dou.gif)
其中包含发现
![](/icons/66345dou2.gif)
请到 developerWorks Java 技术专区查找更多 Java 编程参考资料
![](/icons/66345dou2.gif)
有关作者
自从有了台式计算机以来
![](/icons/66345dou.gif)
Todd Sundsted 就
![](/icons/66345yi.gif)
直在编写软件Software
![](/icons/66345dou2.gif)
他对安全性、分布式计算和发生于大规模细粒度系统中
![](/icons/66345de.gif)
动态行为以及突发
![](/icons/66345de.gif)
行为感兴趣
![](/icons/66345dou2.gif)
除了写作以外
![](/icons/66345dou.gif)
Todd 还做
![](/icons/66345yi.gif)
些编码工作
![](/icons/66345dou2.gif)
可通过
[email protected] 和 Todd 联系
延伸阅读
最新评论