天天看點

fms4 p2p:圖檔分享

這其實關于檔案分享示例的改版,原文示例是基于flex的,我改成flash版本了(大緻原理與上一篇完全相同):

有三個基本類:

1、P2PSharedObject.as 用于定義要分享的(圖檔)資料類

package p2p
{
  import flash.utils.ByteArray;

  public class P2PSharedObject
  {
    
    public var size:Number = 0;
    public var packetLenght:uint = 0;
    public var actualFetchIndex:Number = 0;
    public var data:ByteArray;
    public var chunks:Object = new Object();
    
    public function P2PSharedObject()
    {
    }
  }
}
      

2、LocalFileLoader.as 用于浏覽本地圖檔并加載到舞台,将自動将圖檔以約64000 byte左右為機關,分成一塊一塊

package p2p
{
  import flash.events.Event;
  import flash.events.EventDispatcher;
  import flash.events.IOErrorEvent;
  import flash.events.ProgressEvent;
  import flash.events.SecurityErrorEvent;
  import flash.events.StatusEvent;
  import flash.net.FileReference;
  import flash.utils.ByteArray;
  
  
  public class LocalFileLoader extends EventDispatcher
  {
    public function LocalFileLoader()
    {
      
    }
    
    
    private var file:FileReference;
    public var p2pSharedObject:P2PSharedObject;
    
    
    public function browseFileSystem():void {
      file = new FileReference();
      file.addEventListener(Event.SELECT, selectHandler);
      file.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
      file.addEventListener(ProgressEvent.PROGRESS, progressHandler);
      file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler)
      file.addEventListener(Event.COMPLETE, completeHandler);
      file.browse();
    }
    
    protected function selectHandler(event:Event):void {
      writeText("fileChosen");
      
      writeText(file.name+" | "+file.size);
      
      file.load();
    }
    
    protected function ioErrorHandler(event:IOErrorEvent):void {
      writeText("ioErrorHandler: " + event);
    }
    
    protected function securityErrorHandler(event:SecurityErrorEvent):void {
      writeText("securityError: " + event);
    }
    
    protected function progressHandler(event:ProgressEvent):void {
      var file:FileReference = FileReference(event.target);
      writeText("progressHandler: bytesLoaded=" + event.bytesLoaded + "/" +event.bytesTotal);
      
    }
    
    protected function completeHandler(event:Event):void {
      writeText("completeHandler");
      
      p2pSharedObject = new P2PSharedObject();
      p2pSharedObject.size = file.size;
      p2pSharedObject.packetLenght = Math.floor(file.size/64000)+1;
      p2pSharedObject.data = file.data;
      
      
      p2pSharedObject.chunks = new Object();
      p2pSharedObject.chunks[0] = p2pSharedObject.packetLenght+1;
      for(var i:int = 1;i<p2pSharedObject.packetLenght;i++){
        p2pSharedObject.chunks[i] = new ByteArray();
        p2pSharedObject.data.readBytes(p2pSharedObject.chunks[i],0,64000);
        
      }
      // +1 last packet
      p2pSharedObject.chunks[p2pSharedObject.packetLenght] = new ByteArray();
      p2pSharedObject.data.readBytes(p2pSharedObject.chunks[i],0,p2pSharedObject.data.bytesAvailable);
      
      p2pSharedObject.packetLenght+=1;
      
      writeText("----- p2pSharedObject -----");
      writeText("packetLenght: "+(p2pSharedObject.packetLenght));
      
      
      dispatchEvent(new Event(Event.COMPLETE));
    }
    
    protected function writeText(str:String):void{
      var e:StatusEvent = new StatusEvent(StatusEvent.STATUS,false,false,"status",str);
      
      dispatchEvent(e);
    }
  }
}
      

3、P2PFileShare.as 用于處理P2P檔案分享(即從一個peer端發送另一個peer端)

package p2p
{
  import flash.events.Event;
  import flash.events.EventDispatcher;
  import flash.events.NetStatusEvent;
  import flash.events.StatusEvent;
  import flash.net.GroupSpecifier;
  import flash.net.NetConnection;
  import flash.net.NetGroup;
  import flash.net.NetGroupReplicationStrategy;
  import flash.utils.ByteArray; 
  
  public class P2PFileShare extends EventDispatcher
  { 
    
    public var connected:Boolean = false;
    
    public var netConnection:NetConnection;
    
    
    public var netGroup:NetGroup;
    
    private const SERVER:String = "rtmfp://localhost/";
    private const DEVKEY:String = "HelloServer";
    
    public var p2pSharedObject:P2PSharedObject;
    
    public function P2PFileShare()
    {
    }
    
    public function connect():void{
      netConnection = new NetConnection();
      netConnection.addEventListener(NetStatusEvent.NET_STATUS,netStatus);        
      netConnection.connect(SERVER+DEVKEY);
    }
    
    public function startSharing(p2pSharedObject:P2PSharedObject):void{
      triggerEvent("startSharing - chunks shared: "+p2pSharedObject.packetLenght);      
      this.p2pSharedObject = p2pSharedObject;     
      netGroup.addHaveObjects(0,p2pSharedObject.packetLenght);
    }
    
    public function startReceiving():void{
      triggerEvent("startReceiving");     
      p2pSharedObject = new P2PSharedObject();
      p2pSharedObject.chunks = new Object();      
      receiveObject(0);
    }
    
    
    protected function onGroupConnected():void{
      netGroup.replicationStrategy = NetGroupReplicationStrategy.LOWEST_FIRST;
      
    }
    
    protected function netStatus(event:NetStatusEvent):void{
      triggerEvent(event.info.code);
      
      switch(event.info.code){
        case "NetConnection.Connect.Success":
          setupGroup();
          break;
        
        case "NetGroup.Connect.Success":
          connected = true;
          
          onGroupConnected();
          
          break;
        
        case "NetGroup.Replication.Fetch.SendNotify": // e.info.index
          triggerEvent("____ index: "+event.info.index);
          
          break;
        
        case "NetGroup.Replication.Fetch.Failed": // e.info.index
          triggerEvent("____ index: "+event.info.index);
          
          break;
        
        case "NetGroup.Replication.Fetch.Result": // e.info.index, e.info.object
          //triggerEvent("____ index: "+event.info.index+" | object: "+event.info.object);
          
          netGroup.addHaveObjects(event.info.index,event.info.index);
          
          p2pSharedObject.chunks[event.info.index] = event.info.object;
          
          if(event.info.index == 0){
            p2pSharedObject.packetLenght = Number(event.info.object);
            triggerEvent("p2pSharedObject.packetLenght: "+p2pSharedObject.packetLenght);
            
            receiveObject(1);
            
          }else{
            if(event.info.index+1<p2pSharedObject.packetLenght){
              receiveObject(event.info.index+1);
            }else{
              triggerEvent("Receiving DONE");
              triggerEvent("p2pSharedObject.packetLenght: "+p2pSharedObject.packetLenght);
              
              p2pSharedObject.data = new ByteArray();
              for(var i:int = 1;i<p2pSharedObject.packetLenght;i++){
                p2pSharedObject.data.writeBytes(p2pSharedObject.chunks[i]);
              }
              
              triggerEvent("p2pSharedObject.data.bytesAvailable: "+p2pSharedObject.data.bytesAvailable);
              triggerEvent("p2pSharedObject.data.length: "+p2pSharedObject.data.length);
              
              dispatchEvent(new Event(Event.COMPLETE));
            }
          }
          
          
          break;
        
        case "NetGroup.Replication.Request": // e.info.index, e.info.requestID
          netGroup.writeRequestedObject(event.info.requestID,p2pSharedObject.chunks[event.info.index])
          //
          
          triggerEvent("____ ID: "+event.info.requestID+", index: "+event.info.index);
          break;
        
        default:
          break;
      }
    }
    
    protected function setupGroup():void{
      triggerEvent("setupGroup");     
      var spec:GroupSpecifier = new GroupSpecifier("myGroup");
      spec.serverChannelEnabled = true;
      spec.objectReplicationEnabled = true;   
      netGroup = new NetGroup(netConnection,spec.groupspecWithAuthorizations());
      netGroup.addEventListener(NetStatusEvent.NET_STATUS,netStatus);     
    }
    
    
    protected function receiveObject(index:Number):void{
      netGroup.addWantObjects(index,index);
      p2pSharedObject.actualFetchIndex = index;
    }
    
    protected function triggerEvent(str:String):void {
      trace("P2pFilShare.triggerEvent 被調用:str->", str);
      var e:StatusEvent = new StatusEvent(StatusEvent.STATUS,false,false,"status",str);
      
      dispatchEvent(e);
    }
    
    
    
  }
}
      

最後的flash peer端:

package {

  import fl.controls.Button;
  import fl.controls.TextArea;
  import fl.controls.TextInput;
  import flash.display.StageAlign;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  import flash.events.StatusEvent;
  import flash.display.Loader;
  import flash.display.MovieClip;
  import flash.events.MouseEvent;
  import flash.net.NetGroupInfo;
  import p2p.LocalFileLoader;
  import p2p.P2PFileShare;
  import p2p.P2PSharedObject;


  public class p2p_FileShare extends MovieClip {

    private var _btnBrowse:Button;
    private var _btnShare:Button;
    private var _btnReceive:Button;
    private var _txtOutput:TextArea;
    private var _txtReceive:TextInput;
    private var _txtSend:TextInput;

    private var _localFileLoader:LocalFileLoader;
    private var _loader:Loader;
    private var _fileShare:P2PFileShare;

    public function p2p_FileShare(){
      // constructor code     
      init();
    }

    private function init():void {
      this.stage.align = StageAlign.TOP_LEFT;
      this.stage.scaleMode = StageScaleMode.NO_SCALE;

      this._localFileLoader = new LocalFileLoader();
      this._localFileLoader.addEventListener(StatusEvent.STATUS, onStatus);
      this._localFileLoader.addEventListener(Event.COMPLETE, fileLoaderComplete);

      _fileShare = new P2PFileShare();
      _fileShare.addEventListener(StatusEvent.STATUS, onStatus);
      _fileShare.addEventListener(Event.COMPLETE, fileShareComplete);
      

      this._fileShare.connect();
      this._loader = new Loader();
      addChild(_loader);
      _loader.x = 218;
      _loader.y = 43.35;

      this._btnBrowse = btnBrowse;
      this._btnShare = btnStartShare;
      this._btnReceive = btnReceive;
      this._txtOutput = txtOutput;
      this._txtReceive = txtReceive;
      this._txtSend = txtSend;

      this._btnBrowse.addEventListener(MouseEvent.CLICK, _btnBrowse_Click);
      this._btnReceive.addEventListener(MouseEvent.CLICK, _btnReceive_Click);
      this._btnShare.addEventListener(MouseEvent.CLICK, _btnShare_Click);
    }

    private function onStatus(event:StatusEvent):void {
      writeText(event.level);
      if (event.level == "NetGroup.Connect.Success"){
        _btnShare.enabled = false;
        _btnReceive.enabled = true;
      }
      try {
        refreshInfo();
      } catch (e:Error){

      }
    }

    private function fileLoaderComplete(event:Event):void {
      writeText("fileLoaderComplete");
      _loader.unload();
      _loader.loadBytes(_localFileLoader.p2pSharedObject.data);
      this._fileShare.startSharing(this._localFileLoader.p2pSharedObject);
      this._btnShare.enabled = true;
      this._btnReceive.enabled = false;
      this._btnBrowse.enabled = false;
    }

    private function fileShareComplete(event:Event):void {
      writeText("fileShareComplete");
      _loader.unload();
      _loader.loadBytes(_fileShare.p2pSharedObject.data);
    }

    private function writeText(txt:String):void {
      trace("p2p_FileShare.writeText 被調用:txt->", txt);
      this._txtOutput.appendText(txt + "\n");
    }

    private function _btnBrowse_Click(e:MouseEvent):void {
      this._localFileLoader.browseFileSystem();
    }
    
    private function _btnShare_Click(e:MouseEvent):void {
      this._fileShare.startSharing(this._localFileLoader.p2pSharedObject);
      this._btnShare.enabled = false;
    }
    
    
    private function _btnReceive_Click(e:MouseEvent):void {
      this._fileShare.startReceiving();
    }


    protected function refreshInfo():void {
      var obj:NetGroupInfo = this._fileShare.netGroup.info;
      _txtReceive.text = obj.objectReplicationReceiveBytesPerSecond + "";
      _txtSend.text = obj.objectReplicationSendBytesPerSecond + "";
    }
  }

}
      

運作截圖

fms4 p2p:圖檔分享

作者:菩提樹下的楊過