fms4 p2p:图片分享

这其实是http://www.flashrealtime.com/file-share-object-replication-flash-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 + "";
		}
	}

}

运行截图

posted @ 2010-11-30 10:09  菩提树下的杨过  阅读(2770)  评论(0编辑  收藏  举报