熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

基於JXTA的P2P應用開發

2013-11-23 19:50:32  來源: Java高級技術 

  PP計算被Intel喻為第三代網絡革命的點對點分散式網絡架構JXTA是Sun旨在建立PP通用技術基礎的計劃定義了一組PP協議本文以一個簡單的聊天應用為例介紹基於JXTA的PP應用開發
  概述
  PP即PeertoPeer稱為對等連接或對等網絡是一種點對點計算模式JXTA是項目創始人Sun首席科學家Bill Joy二十多年醞釀的結晶JXTA技術是網絡編程和計算的平台用以解決現代分布計算尤其是PP計算中出現的問題JXTA協議是一組為PP網絡計算而設計的協議共六種這六種協議分別是Peer Discovery ProtocolPeer Resolver ProtocolPeer Information ProtocolPeer Membership ProtocolPipe Binding Protocol以及Peer Endpoint Protocol利用這些協議我們可以讓消息跨越多個網絡發送到網絡上的任意其他Peer這些協議是所有Java PP應用的基礎請參見圖一的JXTA應用體系(該圖來自)
   
  圖一JXTA應用體系
  本文的例子是一個基於JXTA的PP應用Peer可以利用它聊天它允許Peer把自己注冊到網絡上發送消息給其他Peer或者從其他Peer接收消息
  編寫JXTA應用要求JXTA內核以jxtajar JAR文件的形成存在(jxtajar文件可以從下載)jxtajar文件必須在CLASSPATH中
  
  構造JXTA應用並不是一件很復雜的事情只需實現netjxtaplatformApplication接口並提供該接口定義的三個方法init()startApp()和stopApp()下面顯示的SimpleJXTA類就是一個最簡單的JXTA應用(注意程序必須導入netjxtadocumentAdvertisement類和netjxtapeergroupPeerGroup接口init()方法需要它們)
  
  // 最簡單的JXTA應用
  import netjxtaplatformApplication;
  import netjxtadocumentAdvertisement;
  import netjxtapeergroupPeerGroup;
  
  public class SimpleJXTA implements Application {
  public void init(PeerGroup group
   Advertisement adv) {
  }
  public int startApp(String[] args) {
   return ;
  }
  public void stopApp() {
  }
  }
  作為一個Java應用上面的程序是否遺漏了static void main()方法呢?其實與普通Java應用相比JXTA應用的運行方式有所不同JXTA應用要求啟動JXTA平台JXTA平台啟動之後它將啟動所有在jxtaConfig配置文件中指定的應用JXTA平台啟動一個應用時首先調用應用的init()方法接著調用startApp()方法
  JXTA聊天程序
  本文的聊天應用改編自JXTA Shell軟件包的Talk程序設計這個應用的主要目的是為了學習JXTA編程它很簡單與基於Java Socket的許多聊天應用相比它缺少許多高級特性且不具備強健的錯誤控制機制然而這個程序用到了許多重要的JXTA類和接口初學者可以由此開始深入了解JXTA
  程序有一個很簡單的GUI如圖二所示
   
  圖二程序界面
  所有來自聊天用戶的消息格式為[用戶名字] 消息聊天程序本身報告的信息都以>開頭
  
  聊天程序的業務規則為
  
  ● 用戶在登錄文本框中輸入自己的名字並點擊登錄按鈕登錄
  
  ● 用戶名字必須唯一任何兩個用戶不能有相同的名字如果某個用戶輸入的名字正在被其他用戶使用則應用將報告該信息正在試圖登錄的用戶必須改變自己的名字
  ● 成功登錄後用戶在消息輸入框中輸入消息所有消息將以廣播的形式發送給當前已經登錄的所有用戶包括消息發送者本身
  登錄
  登錄的目的不是進行身份驗證任何擁有聊天程序的人都可以加入聊天登錄的目的是為了讓其他用戶知道當前用戶的存在使得聊天程序能夠發送消息或者從其他聊天用戶接收消息
  消息通過管道從一個Peer傳遞到另一個Peer管道由netjxtapipe包裡面的Pipe接口描述管道是在兩個JXTA應用或服務之間傳遞消息的核心機制它為兩個Peer之間的通信提供了簡單的單向的異步的通道換句話說管道把多個Peer終端連接到了一起接收端稱為輸入管道發送端稱為輸出管道要讓輸出管道能夠把消息發送到接收管道兩個管道首先必須互相認知對方例如聊天應用的一個實例能夠把消息發送給另一個實例之前兩個實例必須互相認知對方應用的一個實例必須把自己介紹給其他實例這是如何完成的呢?
  在JXTA術語中讓其他Peer知道某個Peer已經在線叫做廣告(advertising)從技術上看advertising意味著把一個廣告發送給網絡上的所有用戶這裡的廣告可以是任意網絡資源的標識符可以用來描述各種核心對象例如PeerPeerGroupServicePipeContent或EndpointJXTA廣告是與平台無關的一般以XML文檔的形式提供
  
  在聊天程序中由於管道是信息交換的核心對象PipeAdvertisement代表著各個聊天用戶PipeAdvertisement描述了一個管道通信通道管道服務利用它創建關聯的輸入和輸出管道終端
  
  當一個Peer發送它的廣告給另一個Peer它可以期待另一個Peer的回應即發回它的廣告按照這種方式雙方都將擁有對方的廣告廣告由應用緩沖以便以後使用當應用需要廣播一個消息時會用到這些緩沖的廣告JXTA自動在cm子目錄的特定目錄下以文件的形式(文件名字唯一)緩沖廣告對於本文的聊天應用JXTA創建了一個名為edb的目錄在這個目錄下有子目錄AdvGroupsPeerInfoPeersprivatepublic和tmp如圖三所示所有與聊天應用聯系的Peer的所有PipeAdvertisement都保存在Adv目錄下包括聊天應用自己的PipeAdvertisement
  educitycn/img_///gif >
  圖三cm目錄結構
  當一個用戶登錄聊天應用首先檢查所有本地緩沖的PipeAdvertisement如果其中一個緩沖的PipeAdvertisement的用戶名字與聊天用戶輸入的名字相同則聊天應用將向用戶提示名字已經被使用這種提示可能是錯誤的因為以前使用該用戶名字的遠程用戶當時不一定登錄另外由於聊天應用緩沖了它自己的PipeAdvertisement用戶不能在下一次會話中使用同一個名字因此如果必要在啟動應用之前可以清除Adv目錄
  當聊天應用搜索完所有本地緩沖的PipeAdvertisement且不能找到匹配的用戶名字時它將把搜索擴展到遠程用戶如果用戶名字已經被某個遠程用戶使用聊天應用將向試圖登錄的用戶提示該名字不可用
  至此為止聊天應用已經可以發送消息為了接收消息必須啟動執行監聽任務的線程
  
  sendAll()方法提取所有本地緩沖的PipeAdvertisement以用戶輸入的文字為基礎構造出一個消息然後把消息發送給每一個PipeAdvertisement已經緩沖的遠程用戶首先sendAll()方法獲取發送者的用戶名字接著sendAll()方法調用getAllPipeAd()方法獲取一個包含所有本地緩沖的PipeAdvertisement的Vector然後sendAll()方法利用循環依次訪問各個PipeAdvertisement利用Pipe接口的createOutputPipe()方法構造一個OutputPipe對象調用createOutputPipe()方法時傳入找到的PipeAdvertisement如下所示
  
  // 廣播廣告
  int length = pipessize();
  for (int i = ; i<length; i++) {
  PipeAdvertisement adv = (PipeAdvertisement) pipesget(i);
  OutputPipe pipeOut = null;
  try {
   // 這個值僅用於測試
   // 可能需要等待更長時間
   pipeOut = pipecreateOutputPipe(adv PipeNonBlocking );
  } catch (Exception e) { }
  如果成功地創建了OutputPipe對象接下來開始構造Message對象
  
  if (pipeOut != null) {
  Message msg = null;
  String userInput = null;
  InputStream inputStream = null;
  try {
   // 構造一個消息
   msg = pipecreateMessage();
  Message對象的push()方法用來以InputStream的形式插入一組數據因此先把用戶消息(messageBoxgetText())轉換成一個Byte數組再轉換成ByteArrayInputStream然後把InputStream以參數的形式提供給push()方法另外我們還要在消息中加入發送者的名字為此先從sender字符串構造出另一個InputStream再把它作為參數傳遞給push()方法
  inputStream = new ByteArrayInputStream(
   messageBoxgetText()getBytes());
  msgpush(SENDER_TEXT inputStream);
  inputStream = new ByteArrayInputStream(sendergetBytes());
  msgpush(SENDER_ID inputStream);
  准備好Message對象之後把它作為參數傳遞給OutputPipe類的send()方法把消息發送給接收的Peer
  pipeOutsend(msg);
  最後關閉OutputPipe
  pipeOutclose();
  run()方法執行與sendAll()方法相反的操作run()方法創建一個InputPipe監聽傳入的消息提取出Message對象的用戶名字和內容並調用toDisplay()方法顯示出消息
  首先run()方法利用當前Pipe對象(pipe)的createInputPipe()方法創建一個InputPipe如果createInputPipe()方法返回null則顯示不能打開InputPipe錯誤信息反之如果成功地創建了InputPiperun()方法開始一個無結束條件的while循環監聽傳入的消息如下所示
  
  // 監聽傳入的消息
  while
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27536.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.