Peer-to-Peer Sockets 工程入门

版权声明:能够任意转载,转载时请务必以超连接形式标明文章原始出处和做者信息及本声明
做者:
Brad Neuberg ;gracepig
原文地址:
http://www.onjava.com/pub/a/onjava/2003/12/03/p2psockets.html
中文地址:
http://www.matrix.org.cn/resource/article/43/43854_Peer-to-Peer-Sockets.html
关键词: Peer-to-Peer Sockets

Peer-to-Peer (P2P)Sockets工程在JXTA peer-to-peer虚拟网络从新实现了对应于标准TCP/IP网络中的Java标准的Socket,ServerSocket,和InetAddress等类。该工程同时还引入了一些注入Jetty web server,Apache XML-RPC客户端和服务器库,Apache Jasper JSP引擎之类的流行web package。使这些服务能够运行在Peer-to-Peer Sockets 的框架下。

在这片文章结束的时候,你会理解对P2P Sockets packages的需求和以及开发它的动机,学会怎么配置P2P Socket 库使之在你的系统上可以运行,学会怎么样创建P2P的服务器和客户端Socket,怎么使用P2P的InetAddress 类,还包括框架下的安全问题以及它的局限性。

动机

P2P Socket工程的设计的使用对象是对如下几个领域有兴趣的开发者:
●将Internet回归到end-to-end的原则当中
●一种绕过ICANN和Verisign的替代peer-to-peer域名系统,这个系统是彻底分布式的,对更新拥有比标准DNS快的多的响应速度。
●一种任何人均可以创建活着使用网络服务的Internet,及时他们使用动态的IP地址或是没有IP地址,或是只有内网地址(NAT),或者是在ISP的防火墙以后。
●一个每个Peer都可以自动的创建一个Web Server,提供XML-RPC服务,可以快速的将这种服务提供给其余的Peer。
●使为Peer-to-Peer网络添加Java Socket和ServerSocket 的应用更加容易
●享受更酷的科技

P2P Socket 工程在JXTA peer-to-peer网络上从新实现了标准java.net报当中的类。一些人可能要问“难道标准TCP/IP socket和ServerSocket不是已是peer-to-peer的了吗?”标准的TCP/IP socket和server socket在理论上是peer-to-peer的,不过因为防火墙,NAT设备,以及DNS所存在的政治或是技术的问题,在实际上却没有作到这一点。首先,Internet上的许多peer使用的都是经过DHCP协议取得的动态IP,这些IP由经过NAT设备共享和过滤,还有一些IP地址因为防火墙的限制,很难被访问到。在这样的条件下创建server socket应用要么是不可能的,要么就须要在应用层进行精妙的控制来绕过这些限制。其次,TCP/IP Socket依赖于DNS系统来将用户友好的主机名转变为IP地址。DNS在理论上就是办分布式的,可是在管理层面上,DNS是在ICANN下集中式管理的,而ICANN是一个反应迟钝的,没有创新意识的组织。再次,标准的DNS对对那些过滤或是使用动态IP地址的edge-peer支持的并很差,更新须要花费很长的时间传播下去并且并不提供presence信息。对那些想要开发可以扩展DNS到新的领域(例如将即时消息的用户名和存在信息加入到DNS)的新应用的开发者来讲,DNS系统的技术和政治因素阻碍了他们的工做。

JXTA是一个用于在TCP/IP之上创建peer-to-peer覆盖网络的开源工程。在网络中的没一个peer都会被分配到一个和IP地址相似的号码,即时他们没有固定的IP地址或是出在防火墙以后。在JXTA 网络上的super-peer通信运行应用层的路由协议来储存例如若是到达其余的peer,如何加入peer group,其余peer提供了怎么样的内容之类的信息。JXTA应用层在Peer之间提供了中继的代理服务,是出在防火墙或是NAT后的Peer能够正常的通讯。Peer能够本身组织成为Peer Group,这样能够将全部的查询请求限定在natural security container当中。任何peer均可以分布式的创建并发布一个peer group,其余的Peer经过使用其余的super-peer能够搜索并发现这些peer group。Peer之间的通讯经过pipe的方式来进行,这和Unix系统当中的Pipe很是的相似。Pipe是对两个peer之间通信方式的一种抽象,它帮助peer互相通信,即便他们处在不一样的网络区域当中。

JXTA是一种很是强大的框架。可是,它并非一种容易学习的框架,将现有的软件移植到JXTA下也不是一件容易的事情。P2P Sockets成功地将JXTA隐藏起来,使之看起来就像是传统的TCP/IP网络。若是peer想要成为服务器,他只须要简单的使用包含他们想使用的domain name和端口的P2P Server Socket就能够了。P2P的客户端能够经过host名和特定的端口号来创建Socket链接访问那些服务。Host能够被解析为域名,例如www.nike.laborpolicy,或是IP地址,例如44.22.33.22。在这些场景以后,host实际被解析为JXTA原语,而不是被解析为DNS或是TCP/IP。举例来讲:域名www.nike.laborpolicy其实是JXTA peer group 的广告消息中的一个NAME字段。P2P Sockets和Server socket 与正常的TCP/IP Socket和ServerSocket的使用方法彻底相同。咱们为但愿了解内幕和那些已经懂得JXTA的用户提供了一张表(http://www.onjava.com/onjava/2003/12/03/examples/table.html),在这张表中能够查询到传统TCP/IP概念上的域名,IP地址等概念和JXTA中对等概念的对应关系。

使用这种方式的好处是多方面的。首先,程序员能够将他们在标准TCP/IP Socket和Server Socket的知识应用到JXTA peer-to-peer网络当中而不须要专门学习JXTA。其次,全部的P2P Socket 的代码都是标准java.net中类的子类,例如java.net.Socket,因此现存的网络应用能够很容易的移植到peer-to-peer网络当中。 P2P Socket工程已经将不少现存的软件移植到了peer-to-peer网络当中,其中包括web服务器(Jetty),它能够接收请求,被在peer-to-peer 网络上提供内容服务;一个servlet和JSP引擎(Jetty 和 Jsper),它可使现存的servlet和JSP直接在P2P网络中应用;一个XML-RPC客户端和服务器(Apache XML-RPC),它能够访问和对外提供P2P XML-RPC 端点;一个HTTP/1.1客户端(Apache Commons HTTP-Client),它能够访问P2P的web 服务器;一个网关(Smart Cache),它能够是现有浏览器访问P2P的P2P web 站点;和WikiWiki(JSPWiki),它可以在你的主机上创建Wiki站点,使其余的Peer能够经过P2P网络访问,并编辑。全部的这些软件在移植以后都可以正常的使用而且和之前看起来彻底同样。P2P Socket的抽象很是的成功,移植这些软件所花费的时间仅仅是30分钟到几个小时不等。P2P Socket工程是彻底开源的,大部分都采用BSD-type证书,因为是使用Java编写的,因此也具备跨平台的特性。

因为P2P Socket是创建在JXTA之上的,因此它能够很容易的处理一些传统的ServerSocket和Socket所不能处理的状况。第一,在P2P Socket上创建的ServerSocket,具备fail-over(不知道怎么翻译,应该是可靠性之类的意思)和易扩展的特性。若是不一样的Peer能够启动ServerSocket使用同一个域名和端口,例如www.nike.laborpolicy 端口号:80。当一个客户端打开P2P socket链接到www.nike.laborpolicy 端口号:80时,它会随机的链接到一个提供一个使用这个域名和端口的主机上。全部的这些服务器Peer可能提供一样的Web页面,这就是能够将用户的请求分布到不一样的服务器之上同时也就使得某一个服务器的崩溃更容易被恢复。这一点和DNS round-robin很是的类似,在DNS round-robin当中一个域名能够被解析为多个IP地址用来进行负载均衡。第二,因为P2P Socket并不使用DNS系统,主机名能够任意指定。用户能够创建他本身的个性结尾,例如www.boobah.cat 或是www.cynthia.goddess,或是应用肯定的名字,例如一个即便消息系统使用Brad GNUberg或是Fidget666看成域名。第三,一个指定域名的服务端口能够分布在全世界不少的Peer当中。举例来讲,假设你有一个虚拟主机名www.nike.laborpolicy,一个Peer能够在80端口提供web页面,另外一个Peer可使用2000端口提供即时消息,最后一个Peer能够在3000端口为其余Peer提供即时的RSS更新。如今一个域名能够由不少分布不一样的Peer协同在一块儿提供服务。

需求与配置
要开发和使用P2P Socket你必须下载和安装一下的这些软件。
JDK 1.4+
P2P Socket只能工做在JDK 1.4或是更新版本的Java虚拟机之上,因为P2P Socket是Java.net.InetAddress的子类,在1.4以前,这个类是final类型的。

Ant 1.5.3+
用来构建和运行P2P Socket以及相似于Jetty 和 Jasper之类的扩展

P2PSockets-1.0-beta1.zip
P2P Socket 的最新发布包

安装和配置好JDK和Ant,并保证它们均可以在命令行下正确运行。将P2PSockets-1.0-beta1.zip解开到硬盘上。在目录名当中不能出现空格,不然P2P Sockets的构建文件不能正常工做。

必须将JAR文件p2psockets/lib/ant-contrib-0.5.jar加入到你的CLASSPATH当中去。在Windows当中可使用下面这个命令:

set CLASSPATH=%CLASSPATH%;c:\p2psockets\lib\ant-contrib-0.5.jar

P2P Sockets的目录包含两个不一样的子目录,test/clientpeer和test/serverpeer,它们中有已经设置好的JXTA配置信息(分别在test/clientpeer/.JXTA和test/serverpeer/.JXTA当中)。若是你想要了解更多的关于JXTA的配置问题,你能够阅读JXTA配置指南。两个测试peer已经被配置为最差的状况下工做模式,也就是peer处在防火墙或是NAT设备以后,也就是说用户必须使用其余的中间Peer来中继它们的请求。若是用户不处在这种环境下,这种配置方式也是能够工做的。使用JXTA的一个好处就是,当你在使用这个系统的时候,它对你的程序几乎是透明的。

当你在测试本文中的代码的时候,你必须链接到Internet。这样作基于一下的两个缘由:首先,例子程序使用Sun提供的公共JXTA服务器来将启动peer引入JXTA网络当中;其次,在一些操做系统上(例如Windows XP, 缺省),网络系统在你没有链接到网络上时会自动关闭,这样就会阻碍运行在同一个主机上的客户端peer和服务器peer互相通信。

创建一个P2P Server Socket

创建一个P2P server Socket的方法和创建一个标准的java.net.ServerSocket彻底同样。html

// start a server socket for the domain
// "www.nike.laborpolicy" on port 100
java.net.ServerSocket server = new java.net.P2PServerSocket("www.nike.laborpolicy", 100);



经过上面的这种方法,咱们能够创建一个server socket在域名www.nike.laborpolicy 端口100上监听客户端请求。在这种状况下,P2PServerSocket的代码将会去搜索一个名字叫作www.nike.laborpolicy的peer group。一旦它找到了这个peer group,它会加入;接着它会建立并发布一个JXTA peer group 的广告消息在当中会有一个依照特定格式的Name域。这个域使用hostname/IP address,例如 www.nike.laborpolicy/44.33.67.22这种格式。咱们使用通配符来搜索基于JXTA rendezvous 服务器上的主机名或是IP地址,例如www.nike.laborpolicy/*来进行在不知道IP地址状况下的搜索,或是采用*/44.33.67.22来进行指定IP地址的搜索。一旦咱们找到或是建立了这个peer group,咱们就能够发布这个JXTA pipe advertisement到这个peer group当中去,在这个广告信息当中使用Name字段设置端口,例如80。

在创建了这个server socket之后,用户能够像使用普通的java.net.ServerSocket同样的使用,等待一个客户端的请求,并得到InputStream或是OutputStream来进行通信:java

java.net.Socket client = server.accept();
// now communicate with this client
java.io.DataInputStream in = new DataInputStream(client.getInputStream());
java.io.DataOutputStream out = new DataOutputStream(client.getOutputStream());
out.writeUTF("Hello client world!");
String results = in.readUTF();
System.out.println(results);



尽管客户端看起来和正常的java.net.Socket很类似,但实际上它已是经过JXTA peer-to-peer网络来进行通信了,请求与响应消息都是经过其余的peer进行中继来穿越NAT和网络区域的。固然,这一些都是隐藏在后台的。

与普通的server socket不一样,咱们须要初始化并登陆进入咱们的peer-to-peer网络。在咱们创建P2PServerSocket以前,咱们须要进行如下的操做:程序员

// sign into the peer-to-peer network, using
// the username "serverpeer", the password "serverpeerpassword",
// and create/find a scoped peer-to-peer network named "TestNetwork"
java.net.P2PNetwork.signin("serverpeer", "serverpeerpassword", "TestNetwork");



头两个参数是用来登陆进入peer-to-peer网络的用户名和密码。这是在用户设置JXTA Configurator的时候的时候输入的,一个Swing的对话框(在第一运行JXTA 平台的时候会弹出)会容许你在P2P 网络上配置你的Peer。在你本身的应用当中,你能够从命令行和GUI的方式获取这些值。P2P Sockets 包里面预先配置好了两个JXTA Peer分别放在test/clientpeer和test/serverpeer下面。

最后的一个参数(上面例子中的TestNetwork)是你的peer-to-peer网络的惟一名字。创建在P2P Sockets之上的不一样peer-to-peer网络能够在不知道对方存在的状况下共存。客户端和服务器在特定的peer-to-peer网络当中建立和解析它们的server sockets和sockets。最后的一个参数就是你私有的,由应用指定的peer-to-peer网络。若是你建立了一个名叫TestNetwork的server socket而另外一个用户登陆进入一个名叫InstantMessagingNetWork的serversocket,它们就不能找到对方并进行通信。

接下来咱们来看看P2PNetwork这个类是怎样工做的。当你调用signin方法的时候,网络字符串(例子中的TestNetwork)将会被哈希为一个MD5的peer group ID;这样就会保证在咱们以Peer ID搜索的时候,这个应用的名字是全局惟一的。全部的域名和IP地址解析都发生在这个应用的peer group内部。应当注意到在test/clientpeer和test/serverpeer当中使用的JXTA配置文件都将使用Sun rendezvous服务器做为加入JXTA网络的引导服务器;当你想要使用其余的初始服务器时,你须要修改配置文件。

对于程序员来讲,你能够根据本身的应用或是所建立网络的类型选择本身的网络名,例如:MyApplicationsNetwork 或是 AcmeCompanyInformationNetwork。

最终的代码以下所示:web

import java.io.InputStream;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.P2PServerSocket;
import java.net.P2PNetwork;
public class ExampleServerSocket {
   public static void main(String args[]) {
      try {
         // sign into the peer-to-peer network,
         // using the username "serverpeer", the password "serverpeerpassword",
         // and create/find a scoped peer-to-peer network named "TestNetwork"
         System.out.println("Signing into the P2P network...");
         P2PNetwork.signin("serverpeer", "serverpeerpassword", "TestNetwork");
         // start a server socket for the domain
         // "www.nike.laborpolicy" on port 100
         System.out.println("Creating server socket for " + "www.nike.laborpolicy:100...");
         ServerSocket server = new P2PServerSocket("www.nike.laborpolicy", 100);
        
         // wait for a client
         System.out.println("Waiting for client...");
         Socket client = server.accept();
         System.out.println("Client Accepted.");
                
         // now communicate with this client
         DataInputStream in = new DataInputStream(client.getInputStream());
         DataOutputStream out = new DataOutputStream(client.getOutputStream());
         out.writeUTF("Hello client world!");
         String results = in.readUTF();
         System.out.println("Message from client: " + results);
                
         // shut everything down!
         client.close();
         server.close();
      }
      catch (Exception e) {
         e.printStackTrace();
         System.exit(1);
      }
   }
}




使用P2P Socket来链接P2P Server Socket

创建和使用P2P socket链接P2P Server socket同样容易:
首先,须要登陆进去指定的peer-to-peer网络当中:shell

// sign into the peer-to-peer network,
// using the username "clientpeer", the password "clientpeerpassword",
// and find the peer-to-peer network named "TestNetwork"
java.net.P2PNetwork.signin("clientpeer", "clientpeerpassword", "TestNetwork");



接下来,使用指定的主机名和端口号建立你想要链接的socket:apache

java.io.DataInputStream in = new DataInputStream(socket.getInputStream());
java.io.DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String results = in.readUTF();
System.out.println(results);
out.writeUTF("Hello server world!");





下面是完整的代码:浏览器

import java.io.InputStream;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.net.Socket;
import java.net.P2PSocket;
import java.net.P2PNetwork;

public class ExampleClientSocket {
   public static void main(String args[]) {
      try {
         // sign into the peer-to-peer network,
         // using the username "clientpeer", the password "clientpeerpassword",
         // and find a network named "TestNetwork"
         System.out.println("Signing into the P2P network..");
         P2PNetwork.signin("clientpeer", "clientpeerpassword", "TestNetwork");
                
         // create a socket to connect to the
         // domain "www.nike.laborpolicy" on port 100
         System.out.println("Connecting to server socket! at " + "www.nike.laborpolicy:100...");
         Socket socket = new P2PSocket("www.nike.laborpolicy", 100);
                 System.out.println("Connected.");
                
         // now communicate with this server
         DataInputStream in = new DataInputStream(socket.getInputStream());
         DataOutputStream out = new DataOutputStream(socket.getOutputStream());
         String results = in.readUTF();
         System.out.println("Message from server: " + results);
         out.writeUTF("Hello server world!");
                
         // shut everything down
         socket.close();
      }
          
      catch (Exception e) {
         e.printStackTrace();
         System.exit(1);
      }
   }
}




运行P2P Server Socket和Socket的例子

打开两个不一样的Shell 窗口。在两个窗口当中,键入下面的命令来设置使用Ant构建所需的环境变量(修改环境变量使之指向你安装P2P sockets和JDK的位置):

set p2psockets_home=c:\p2psockets
set JAVA_HOME=c:\j2sdk1.4.1


在两个窗口中,都进入p2psockets的目录,例子源码在p2psockets/src/examples目录下面,名字分别叫作ExampleClientSocket.java和ExampleServerSocket.java。全部的代码都已经编译进入p2psockets/dist/examples目录当中去,可是若是你想要从新编译它们的时候,在其中一个shell当中使用下面的这个命令:

ant clobber build jar

要运行客户端和服务器,在一个窗口当中键入下面的命令来启动例子P2P server socket:

ant example-serversocket-run

你会看到以下的屏幕显示:

Buildfile: build.xml
example-serversocket-run:
Signing into the P2P network...
Using the application peer group name TestNetwork
Waiting for RendezVous Connection.........
Finished connecting to RendezVous.
Creating server socket for
www.nike.laborpolicy:100...
Waiting for client...


在另外一个窗口当中,输入以下的命令启动p2p client socket:

ant example-clientsocket-run

你会在client peer 的窗口当中看到以下的输出:

Buildfile: build.xml
example-clientsocket-run:
Signing into the P2P network..
Using the application peer group name TestNetwork
Waiting for RendezVous Connection......
Finished connecting to RendezVous.
Connecting to server socket at
www.nike.laborpolicy:100...
Connected.
Message from server: Hello client world!



在服务器窗口,你会看到以下的输出:

Buildfile: build.xml
example-serversocket-run:
Signing into the P2P network...
Using the application peer group name TestNetwork
Waiting for RendezVous Connection.........
Finished connecting to RendezVous.
Creating server socket for
www.nike.laborpolicy:100...
Waiting for client...
Client Accepted.
Message from client: Hello server world!



祝贺你,你已经创建了一个简单的peer-to-peer网络,这并无须要你作太多的工做,也没有须要你在基本的Java sockets和server sockets之外的知识。

若是你遇到困难,首先确保你已经链接到互联网上,是否使用Java 1.4+,确保P2P Socket package 所安装的目录名当中没有空格。也许你根据你所使用的特殊网络环境调整你的JXTA网络设置。若是你想要在两个被NAT所阻塞的不一样的机器上运行客户端和服务器Socket例子,也许你是碰到了P2P Sockets所公开的一个bug。

检查一个主机名,IP地址,或是端口号是否被占用
缺省状况下,P2PInetAddress和P2PServerSocket类并不会去检查主机名,IP地址,或是端口号是否被占用。这样作的缘由是应用的开发者可使用独一无二的方法来使用P2P Server Socket而传统的Socket是不能这样作的。举例来讲,不一样的peer能够启动P2P Server sockets使用同一个主机名和端口,经过这种方式来提供容错性和扩展性。若是咱们想要在发现地址已经被占用的时候抛出一个异常的话,这种可能行就被排除了。

尽管如此,系统提供了用于发现主机名,IP地址或是端口号是否被占用的方法。这些是java.net.P2PNameService当中的静态方法。例子以下:安全

boolean nameAvailable = P2PNameService.isHostNameTaken("www.nike.laborpolicy");
boolean portAvailable = P2PNameService.isPortTaken("www.nike.laborpolicy", 80);
boolean addressAvailable = P2PNameService.isIPAddressTaken("33.44.74.12");



在你须要为你的server建立一个惟一的实例的时候能够在建立P2P Server socket以前调用这些方法。(请阅读局限性和安全问题一章,在P2P的域名欺骗)

你已经了解到很多关于P2P Socket和server Socket的东西。接下来的这一章将会介绍若是使用P2P Sockets包所提供的其余与标准TCP/IP兼容的类的技术细节。你并非必定须要了解这些内容,但若是你了解,你可使用这些InetAddress类,本地环回地址(127.0.0.1)或是任播地址(0.0.0.0)。若是你跨过下面的章节,请确保你阅读了文章末尾处局限性和安全问题那一章。

使用P2P InetAddress 类

P2P Sockets 包中包含了对于java.net.InetAddress的一个子类实现。

下面的例子介绍了几种不一样的方法,用来建立一个P2PInetAddress对象。服务器

// Create an InetAddress where we know the host
// name but not the IP address.
// This will not search the network to find the
// corresponding IP address.
InetAddress inetAddr = P2PInetAddress.getByAddress("www.nike.laborpolicy", null);

// Create an InetAddress where we know the IP
// address but not the host name.
// This will not search the network to find the
// corresponding host name.
InetAddress inetAddr = P2PInetAddress.getByAddress("55.32.77.34", null);

// Create an InetAddress where we know both the
// IP address and the host name.
// No searching will occur on the network
byte ipAddress[] = new byte[4];
ipAddress[0] = 55;
ipAddress[1] = 32;
ipAddress[2] = 77;
ipAddress[3] = 34;
InetAddress inetAddr = P2PInetAddress.getByAddress("www.nike.laborpolicy", ipAddress);

// Create an InetAddress object using the hostname.
// The network will be searched for the corresponding IP address
InetAddress inetAddr = P2PInetAddress.getByName("www.boobah.cat");

// Create an InetAddress object using the hostname.  
// The network will be searched for the corresponding IP address
InetAddress inetAddress[] = P2PInetAddress.getAllByName("www.boobah.cat");

// Create an InetAddress object using the IP address.  
// The network will be searched for the corresponding host name
byte ipAddress[] = new byte[4];
ipAddress[0] = 55;
ipAddress[1] = 32;
ipAddress[2] = 77;
ipAddress[3] = 34;
InetAddress inetAddr = P2PInetAddress.getByAddress(ipAddress);

// Get the host name and IP address for the local host
InetAddress inetAddr = P2PInetAddress.getLocalHost();



一旦你建立了一个一个P2PInetAddress对象,你就能够像使用一个正常的InetAddress对象那样使用它:网络

InetAddress inetAddr = P2PInetAddress.getByName("www.boobah.cat");
String hostName = inetAddr.getHostName();
String ipAddressString = inetAddr.getHostAddress();
byte ipAddress[] = inetAddr.getAddress();
boolean isLocalhost = inetAddr.isLoopbackAddress();



P2P Server sockets相比起标准的server socket来讲,拥有一个有趣的问题。因为P2P sockets系统本身实现了一个简单的DNS system,咱们须要一种方法来创建一个InetAddress对象,即便此时主机名还并不存在;明确的一点是咱们并不想搜索整个网络来将给定的主机名解析为IP地址,反之亦然,也是因为两者可能都不存在。咱们可能会使用InetAddress对象来将一个P2PServerSocket绑定到一个新的主机名和IP地址上。P2P Sockets目前重载了标准的getByAddress(String host,byte address[])方法来避免对没有给定的信息解析。因为对于这种信息的解析是没有意思并且是没必要要的,因此这种方法在建立一个P2PInetAddress的对象时是值得推荐的。要检查指定的主机名或是IP地址是否已经被占用,可使用P2PNameService类的方法,具体的使用方法在上一章已经介绍过了。

InetAddress对象能够再启动P2P Sockets和Server Sockets时使用,就和使用标准的Java Sockets和server Sockets同样:

InetAddress inetAddr = P2PInetAddress.getByAddress("www.boobah.cat", null);
ServerSocket server = new P2PServerSocket(inetAddr, 80);
.......
.......
.......
InetAddress inetAddr = P2PInetAddress.getByAddress("www.boobah.cat", null);
Socket server = new P2PSocket(inetAddr, 80);



本地环回(127.0.0.1)地址和任播地址(0.0.0.0)
P2P Sockets包提供了一个广播地址的简单实现,这个地址就是0.0.0.0。在标准的TCP/IP Server Sockets使用方法当中,对于广播的接口是这样介绍的“对于本机上任意一个可用的IP地址启动server socket;不须要知道这个IP地址具体是什么。”在P2P Server Sockets的环境当中,一个主机不能是“multi-home”的,也就是说,就是不能有多余一个的IP地址。取而代之的是,server socket会被指定一个自动生成的主机名,也就是它的JXTA peer名。举例来讲,若是一个peer的名字叫作BradGNUberg,这个peer被给定了一个自动生成的主机名www.BradGNUberg.peer。 缺省情况下,前缀是“www.”,后缀是“.peer”。这些值目前是不能自定义的,但在将来的版本当中会给出这种能力。

咱们使用自动生成的Peer名来解析广播和环回地址:

// In the following example, assume the peer's
// local JXTA name is BradGNUberg.
InetAddress inetAddr = P2PInetAddress.getLocalHost();
ServerSocket socket = new P2PServerSocket(inetAddr, 100);
// returns "www.BradGNUberg.peer"
String hostName = socket.getHostName();




在这段代码运行以前,你必须在localhost和指定端口上启动一个P2PServerSocket。

P2P Server Socket一样提供和标准server sockets相兼容的另外一种特性,尽管这个特性可能不多会被使用。标准的TCP/IP server Socket能够在不指定端口的状况下被启动。这种状况下会启动一个server socket使用随机的“私有”端口about 1024(不知道什么意思)。P2PSocket一样支持了这个功能;若是你启动一个server socket而没有指定主机名,广播接口,或是端口号,一个随机的端口号会在1024和65535之间产生。你能够从server socket上得到这个端口号,而后使用其余的途径通知客户端socket,告诉它一个私有的,随机的端口好已经可使用了。

局限性和安全问题

P2P sockets 工程目前有一下的局限性和安全问题:
●假冒主机名和IP地址的状况在peer当中比较少见,因此如今尚未一种机制用于将指定的主机名和IP地址安全的联系到特定peer或是peer group上。
●网络容易收到DOS(denial-of-service)攻击,当一个peer在网络中大量发送请求或是不断的创建server sockets。
●P2P Socket 报尚未被绑定到JVM Security Manager architecture(JVM安全管理架构)当中,在这个框架之中代码会被根据安全策略放到沙箱之中。一旦一个peer被暴露在网络当中,其余的peer能够利用Java虚拟机的缺陷或是P2P Socket层自己的缺陷来危及这个peer的安全。将peer的代码放到沙箱里面和本地机器的资源格离起来能够保护这个缺陷,但因为P2P Socket在执行以前并不检查安全管理,因此目前这种方法还不可行。将JSP引擎包含在标准的我的电脑上,例如JSP依赖于javac,java编译器上一样是很危险的。将网络路径包含在一种语言的编译器当中也很危险,这是一种攻击计算机取得更高的访问权的经常使用方式。你应该预先编译好你的JSP和servlet,并将它们绑定到你的peer程序当中而不是提供整个的JSP引擎。
●还不支持多播IP地址和多播Socket。
●还不支持UDP Socket。
●一些socket选项,流入SoLinger,并无被支持。
●不支持非阻塞的I/O Socket 管道
●本机的环回socket服务器被暴露给外界,这是不对的。
●不支持SSL/HTTPS
●JXTA的配置器在没有JXTA配置的时候会被激活。这带来了几个问题。首先,这是P2P Sockets暴露给程序员JXTA概念的最后一个地方,其次,它要求用户深刻了解这个配置系统以查找出他是否处在防火墙或是NAT设备以后。将来的工程会自动配置这些属性,加入一种“内省”的方法,来自我感知是否处在防火墙或是NAT设备以后。


版权信息:P2P Socket,包括本文的源代码,都受Sun Project JXTA Software License的保护。

相关文章
相关标签/搜索