论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > Flash AS编程教程
Tag:2.0,3.0菜鸟,游戏,,cs,技巧,源码,,文本,文字,函数,音乐,随机,拖拽,asp,access,xml,mc,视频教程

Flash P2P 通信技巧(AS-Java-AS)

文章类别:Flash AS编程 | 发表日期:2008-10-6 18:07:25


众所周知Flash的功能比较强大,但是有两个功能到目前为止始终无法实现 1是swf的点对点连接 2是swf读写操作文件别想了,靠Flash本身是不可能的, 虽然有传说中的MMSave();等一些隐藏函数,但是毕竟这些未公开的函数了解的人并不多,用起来也不方便。那么究竟有没有其他办法可以扶助实现呢?答 案当然是肯定的。在这里我们需要请出当前最热的两门名副其实的编程语言C++/Java,靠他们来实现你要实现的功能吧。在这里我用Java举 例。 首先我们必须了解 AS如何让Java做事?对于双方来讲唯一应用性最高的途径就是Socket了。 AS1->XMLSocket->send()->Java.Socket->InputStream AS2->XMLSocket->send()->Java.Socket->InputStream AS3->Socket->writh()->flush()->Java.Socket->InputStream as1&2只支持以字符串形式发送socket,而as3支持真正意义上的流,在这里为了兼容和教学简单,我均以字符串形式来实现相互间的通信。 1->AS与Java最基本的通信 1.1 简单Java服务器首先我们来做最简单的单线程Java服务器

复制内容到剪贴板
代码:
import java.io.*; import java.net.*; public class Server extends ServerSocket{      //服务端口号常量(as要求必须大于1024,小于65535)      private static final int SERVER_PORT = 10086;      //申明流的空间      private Socket client;      private BufferedReader in;      private PrintWriter out;      private String src;      //构造函数      public Server() throws IOException{          super(SERVER_PORT);          //监听连接,初始流在进来后读取前,和写入后发送前所存放的空间          Socket socket = accept();          in = new BufferedReader(new InputStreamReader(client.getInputStream()));          out = new PrintWriter(client.getOutputStream(),true);          //循环等待读取信息          while(true){              //读取行信息,注意是以换行符结束的              src = in.readLine();              //如果发送"close",就跳出循环(断开连接)              if(src.equals("close")){                  break;              }              //在收到的信息前加是标识并发回(注意结尾加"\0",这是as的XMLSocket读入每条信息的条件.as3的Socket不需要)              out.println("rev: "+src+"\0");              //以上out.println("xx")相当于out.write("xx");out.flush();的执行效果              System.out.println("msg is "+src)          }          //关闭连接          close();      }               //入口函数...      public static void main (String[] args) throws IOException{          new Server();          } }

这样一个Java的服务器就建好了,Java是同步的事件的驱动是等待的,这个AS是不同的,所以方法对与as区别还是比较大的,具体功能已经注释 的非常清楚。至于具体Java的特性我不是专业的,为了对读者负责我就不做详细介绍了,有兴趣的朋友可以查阅Java相关书籍。接下来呢就是AS的访问 了: 1.2 AS1 与 Java 通信 Action Script 1

复制内容到剪贴板
代码:
var SERVER_PORT = 10086; var SERVER_IP = "127.0.0.1"; var conn = new XMLSocket(); conn.connect(SERVER_IP,SERVER_PORT); conn.onConnect = socketConnect; conn.onData = socketData; function socketConnect(success){      trace("connect"+success);      if(success){          this.send("hello world\r");      } } function socketData(src){      trace(src); }

接触了相对生疏的Java后现在回到AS,感觉就是爽,嘿嘿前三行定义了三个变量,由于as1没有强制类型,所以千万别加上类型修饰符啊,反而会出 错,请注意。 conn.connect(SERVER_IP,SERVER_PORT);连接到socket的服务器。如果连接成功 Java中的 ServerSocket.accept();会返回一个对象,并向下执行。 as的连接成功呢则触发了socketConnect(success)的事件,并且把true的参数传如函数。当然连不到就是false了。成功后就会 发送一个"hello world\r"的字符串,"\r"是回车符,因为Java里我用的是readLine();所以需要看到行的结束。当有数据进来的时候呢就会出发 socketData函数了,这里把信息输出。好了用as1的朋友到此已经成功与Java程序通讯了。 1.3 AS2 与 Java 通信 Action Script 2

复制内容到剪贴板
代码:
var SERVER_PORT:Number = 10086; var SERVER_IP:String = "127.0.0.1"; var conn:XMLSocket = new XMLSocket(); conn.connect(SERVER_IP,SERVER_PORT); conn.onConnect = socketConnect; conn.onData = socketData; function socketConnect(success:Boolean){      trace("connect"+success);      if(success){          this.send("hello world\r");      } } function socketData(src:String){      trace(src); }

以上是fla版,和as1唯一的区别就是有类型定义,这样做无论是时间执行效率还是空间执行效率都会有明显提高。接下去看看真正的Action Script 2代码,将以下代码保存成Socket.as文件,和fla文件放在一起。

复制内容到剪贴板
代码:
class Socket extends XMLSocket{      public function Socket(){          super();      }      public function onConnect(success:Boolean){          trace("connect"+success);          if (success){              this.send("hello world\r");          }      }      public function onData(src:String){          trace(src);      } }

fla里在帧上写

复制内容到剪贴板
代码:
var SERVER_PORT:Number = 10086; var SERVER_IP:String = "127.0.0.1"; var conn:Socket = new Socket(); conn.connect(SERVER_IP,SERVER_PORT);

这才是真正的as2,当然你可以更好的修改Socket,让他符合Server的要求,比如在类里加上一个常量,并写入符合Server要求的方法。

复制内容到剪贴板
代码:
public var msg:String = ""; public function write(src){      msg += src; } public function flush(){      this.send(msg+"\r");      msg = ""; }

这样在fla里发送的方式就改为

复制内容到剪贴板
代码:
conn.write("hello world"); conn.flush();

这样是不是又规范又符合Java的要求了呢?我只是举是一个简单例子,你可以按要求自己再修改。 1。4 AS3 与 Java 通信 Action Script 3 最后是传说中的as3了,这里我们用Socket中的writeUTFBytes();来写字符串。首先来看fla版的

复制内容到剪贴板
代码:
var SERVER_PORT:Number = 10086; var SERVER_IP:String = "127.0.0.1"; var conn:Socket = new Socket(SERVER_IP,SERVER_PORT); conn.addEventListener("connect",socketConnect); conn.addEventListener("socketData",socketData); function socketConnect(event:Event){      event.target.writeUTFBytes("hello world");      event.target.writeByte(10);      event.target.flush(); } function socketData(event:ProgressEvent){      trace(event.target.readUTFBytes(event.target.bytesAvailable)); }

看看这个fla版本的是不是在代码上思路更加清晰呢?所有事件已经全部改为监听的方式,并且所有事件将把事件作为参数传入函数。 bytesAvailable为字节长度,而readUTFBytes的参数是从当前指向的位置读取到参数位置,这样写就是读完。在as2里,如果在事件 触发的函数里写this指向的是触发事件的实例,而as3永远指向所在类的实力,触发事件的实例被记录在传入事件参数的target对象中。 as3更加注重的是oop,在fla里已经体现出来了。接下来就来看看DocmentClass的方法

复制内容到剪贴板
代码:
package{class Run{      private var SERVER_PORT:Number = 10086;      private var SERVER_IP:String = "127.0.0.1";      public function Run(){          //在这里写代码并在flash里设置该类为文档类,和直接写上帧上其实没有区别,入口函数          new ClientSocket(SERVER_IP,SERVER_PORT);      } }}

当然还有一个ClientSocket.as的文件放这个socket客户端类

复制内容到剪贴板
代码:
package {      import flash.net.Socket;      import flash.events.ProgressEvent;      import flash.events.Event;      import flash.events.IOErrorEvent;      public class ClientSocket extends Socket {          public function ClientSocket(ip:String,port:uint) {              super(ip,port);              addEventListener("cennect",socketConnect);              addEventListener("socketData",socketData);              addEventListener("ioError",ioError);          }          public function send(src:String) {              writeUTFBytes(src);              writeByte(10);              flush();          }          private function socketConnect(event:Event) {              send("hello world");          }          private function socketData(event:ProgressEvent) {              trace(readUTFBytes(bytesAvailable));          }          private function ioError(event:IOErrorEvent) {              trace("connect error");          }      } }

入口函数创建了一个客户端的对象,而具体的类的内部构造如上代码所示: 首先创建父类构造函数,再为自己添加监听,当连接时执行socketConnect();发送字符串,注意writeByte(10)是换行符。在as3 的socket类里还有其他的事件,这里因为教学原因所以没有过多的举例,相关可以查阅socket的帮助 close   在服务器关闭套接字连接时调度。 connect   在建立网络连接后调度。(这个监听在教程里已经实现) deactivate   Flash Player 失去操作系统焦点并变为非活动状态时调度。 ioError   在出现输入/输出错误并导致发送或加载操作失败时调度。(以前是在onConnect传入false,而这里是直接引发ioError事件,更规范) securityError   若对 Socket.connect() 的调用尝试连接到调用方安全沙箱外部的服务器或端口号低于 1024 的端口,则进行调度。 socketData   在套接字接收到数据后调度。 (这个监听在教程里已经实现) 2 Java多线程服务器基本的通信做到以后就是修改代码增加功能了,这里我们必须让Java能支持多个线程的连接,这才是服务器呀。

复制内容到剪贴板
代码:
import java.io.*; import java.net.*; public class Server extends ServerSocket{      //服务端口号常量(as要求必须大于1024,小于65535)      private static final int SERVER_PORT = 10086;      //构造函数      public Server() throws IOException{          super(SERVER_PORT);          //监听新连接,为每个连接分配一个线程,将新的连接传入独立线程          Socket socket = accept();          new SocketThread(socket);      }      //入口函数...      public static void main (String[] args) throws IOException{          new Server();          }      //建一个类,该类属于独立的线程,他的每个实例都会在独立的线程里运行      class SocketThread extends Thread{                   //申明流的空间在独立线程里了,因为他属于传送时所需,主线程只是监听有没有新连接          private Socket client;          private BufferedReader in;          private PrintWriter out;          private String src;                       //构造函数          public SocketThread(Socket socket) throws IOException{              //初始客户端的连接为该线程传入的连接              client = socket;              //初始流在进来后读取前,和写入后发送前所存放的空间              in = new BufferedReader(new InputStreamReader(client.getInputStream()));              out = new PrintWriter(client.getOutputStream(),true);              //准备工作完毕,启动该线程              start();          }          public void run(){try {              //循环等待读取信息              while(true){                  //读取行信息,注意是以换行符结束的                  src = in.readLine();                  //如果发送"close",就跳出循环(断开连接)                  if(src.equals("close")){                      break;                  }                  //在收到的信息前加是标识并发回(注意结尾加"\0",这是as的XMLSocket读入每条信息的条件.as3的Socket不需要)                  out.println("rev: "+src+"\0");                  //以上out.println("xx")相当于out.write("xx");out.flush();的执行效果                  System.out.println("msg is "+src)              }              //关闭连接              close();          }catch(IOException e){          }catch(NullPointerException e){              System.out.println("client closed");          }}      } }

修改后的Java主线程监听是否有新的连接,如果有就把这个连接分配到新的线程,让他去监听消息,而自己继续监听连接,这样的思路是不是很清晰呢? 仔细看看其实不是很难,大部分的代码都和前面的一样,只是循环监听信息的代码被放到的独立的线程里面。关于多线程和一些Java的技术问题,为了对大家负 责,我依然谨慎言语,以免误导大家。现在你可以启动多个as对Java进行连接,并且他们之间互不干扰。一个线程对应一个连接,底层的工作非常透明,管理 非常容易。 3 AS 通过Java数据转发实现P2P通信谈到这里,其实要实现这步就非常容易了,原理上只要将本来Java收到后返回的信息,发到别人这里去,就可以了。原理 如下所示 flash_1 -> Java -> flash_2 flash_2 -> Java -> flash_3 flash_3 -> Java -> flash_1 这样任何两个flash之间都能通过java转发了,现在只有一个问题,就是Java怎么知道我的信息要发给谁?其实很简单我们在每个连接连入的时候发送 一条注册信息,让Java知道我的名字,而别人只要在字符串前加上我的名字就可以了。那么在Java里 我们需要两个功能 1个是增加和删除自己的标识 2是识别字符串中哪些是名字,哪些是信息这里我们用到方法是<空格> "r s1";这样的一条信息过去,Java服务器要处理为该连接添加一个标识s1,而在这以后任何客户端只要发送 "s1 Hello";就会把"Hello"这个字符串发送给标识为s1的客户端,这样两个flash之间就完全实现了数据互通 "u s1";当离开的时候可以用这个代码来删除s1的标识符为了简单和安全,我们可以暂设为标识必须是两位,以字母开头,这样的组合已经超过千种,绝对够用 了。这样只要判断空个所出现的位置即可,如果是第二位就是注册或卸载标识,如果是第三位就是字符转发了,如果都没有,那就是错误信息。把上面的Run里的 out.println("rev: "+src+"\0");改成以下信息就可以判断信息是注册还是卸载了

复制内容到剪贴板
代码:
//屏蔽所有长度小于4的信息,不做处理. if(line.length()<4){      out.write("error: length<4");      out.flush();      line = in.readLine();      continue; } //命令字符 if (line.charAt(1)==' '){      //相应客户端命令请求      name = line.substring(2);      switch (line.charAt(0)) {      case 'r':          //注册客户端          if (!registered && name.length()==2){              //为自己加一个ID              Server.clientID.put(name,client);              registered = true;              //返回注册成功              out.write("registeration successed");              out.flush();          }          break;      case 'u':          //删除客户端          Server.clientID.remove(name);          registered = false;          break;      } }else if (line.charAt(2)==' '){      //这里是转发代码; }

当然这里用的一些API在前面还要声明过。在线程类里增加两条申明

复制内容到剪贴板
代码:
private String name; private boolean registered;

构造函数里

复制内容到剪贴板
代码:
registered = false;

当然最重要的是还要在Server的主线程里声明一个放ID的容器

复制内容到剪贴板
代码:
public static HashMap clientID = new HashMap();

这样每个连接都有自己的ID了 现在要做的是在转发了,在上面的转发代码的地方写

复制内容到剪贴板
代码:
send(line.substring(0,2),line.substring(3));

当然send函数还没有定义呢,现在定义

复制内容到剪贴板
代码:
public boolean send(String id, String src) throws IOException {      //读取标识的地址      Socket socket = (Socket)Server.clientID.get(id);      if (socket != null){          out = new PrintWriter(socket.getOutputStream(), true);          out.write(src);          out.flush();          return true;      }else{          return false;          } }

这里我加入了判断id是否存在,当不存在就没有任何操作,并且将操作结果成功与否返回,在send的时候就可以分类成功或不成功分别做什么了。 马上来开两个AS吧,用到我们刚才第一章节里自己封装的as2,把加载成功的地方改成send("r c1\r");和send("r c2\r"); Action Script 2

复制内容到剪贴板
代码:
//file1 var SERVER_PORT:Number = 10086; var SERVER_IP:String = "127.0.0.1"; conn:Socket = new Socket(); conn.connect(SERVER_IP,SERVER_PORT); conn.onConnect = function (success:Boolean){      if (success){          write("r c1");          flush();      } } //file2 var SERVER_PORT:Number = 10086; var SERVER_IP:String = "127.0.0.1"; conn:Socket = new Socket(); conn.connect(SERVER_IP,SERVER_PORT); conn.onConnect = function (success:Boolean){      if (success){          write("c2 hello");          flush();      } }

依次运行file1,file2看看,file2运行的时候是不是成功收到了一个hello呢?嘿嘿。这样做虽然底层还是没有实现P2P,但是效果已经达到,如果还是觉得不够理想,那么可以每个客户端都绑定一个Java的ServerSocket,负责收信息,并转发给同绑定Flash,这样虽然没有实现swf的p2p,但是在底层已经p2p了。 [完毕...   答疑和下载 在11楼] <1 AS与Java最基本的通信> .. OK <2 Java多线程服务器> .. OK <3 AS 通过Java数据转发实现P2P通信> .. OK <4 将P2P方式用类封装资源免费下载> .. OK AS.Socket.P2P.rar (7.06 KB)

视频教程列表
文章教程搜索
 
Flash AS推荐教程
Flash AS热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058