这其实是http://www.flashrealtime.com/file-share-object-replication-flash-p2p/ 中关于文件分享示例的改版,原文示例是基于flex的,我改成flash版本了(大致原理与上一篇完全相同):
有三个基本类:
1、P2PSharedObject.as 用于定义要分享的(图片)数据类
代码语言:javascript复制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左右为单位,分成一块一块
代码语言:javascript复制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端)
代码语言:javascript复制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端:
代码语言:javascript复制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 "";
}
}
}
运行截图