用as3 serverSocket 做服务端,实现web客户端

听说,AIR2.0 有serverSocket可以做服务端,一时兴起,于是来试试,在官方看了一个示例,挺简单的(ps简单就意味着功能太少),就想来做一个聊天服务器(之前学完用FMS做聊天室,但毕竟是第三方服务器,受限制的,始终希望能自己做服务器,改天学C++);

       最初都是用的air应用做的客户端连接不成问题。后来做web的客户端,连接不成功,服务端收到消息<policy-file-request/> 客户端提示安全性错误,Erorr:#2048  对于服务端的消息最初并不懂啥意思,于是摆渡。资料到是不少,意思是说,web客户端需要客户端提供安全策略文件,也就是crossdomain.xml,我检查http服务器根目录也有这个文件,并且内容如下:

<?xml version="1.0" ?>
 <cross-domain-policy>
     <site-control permitted-cross-domain-policies="all"/>

    <allow-access-from domain="*" to-ports="*" />

 </cross-domain-policy>

想想不对,这是客户端找服务端要文件,又以为是服务端应用程序的相同目录也要放一个,于是也放一个进去(是不是挺傻的);测试,还是不行;再摆渡,搜到了flashPlayer的socket读取安全策略的原理,原来flashPlayer 最初会去服务端的843端口找策略文件,找不到然后才去指定的端口找,如果都没有crossdomain,就会抛出安全错误。 在网上找资料,是说要单独建一个843端口服务端,专门侦听843端,都是用的java服务端(Java俺也不怎么懂); 不过我只看了一个关键性代码如下:

var xml:XML =<cross-domain-policy>  
       <site-control permitted-cross-domain-policies="all"/>  
       <allow-access-from domain=\"*\" to-ports=\"*\"/>
       </cross-domain-policy>

那些 \ 我不懂是干啥的,我放到FB 里不正常,要把四个 \ 都去掉,反正大致原理就是:843服务端收到客户端请求时,就把这个xml发送给客户端,然后再把socket关掉,由于843端口把客户端关了,客户端会重新连接,因为flashplayer之前收到了策略文件,可以访问服务端,所以就不会再去找843端口,直接连接到正常的服务端口去。

我不懂JAVA ,所以就用air单独又建一个服务端,端口为843;FB源代码如下:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:mx="library://ns.adobe.com/flex/mx"
        width="300" height="300" creationComplete="init()">
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 
 <fx:Script>
 <![CDATA[
 import flash.events.ServerSocketConnectEvent;
 import flash.net.ServerSocket;
 import flash.net.Socket;
   
 private var serverSocket:ServerSocket;
 private var localIP:String="192.168.1.253";//我的电脑IP
 private var localPort:int=843;     //一定要是843端口
 protected function init():void{
 serverSocket = new ServerSocket();
 serverSocket.bind(localPort,localIP  );
 serverSocket.addEventListener(ServerSocketConnectEvent.CONNECT, onConnect );
 serverSocket.listen();
 }
  //客户端连接事件;
 protected function onConnect(e:ServerSocketConnectEvent):void{
   var tmpsocket:Socket=e.socket;
   var xml:XML =<cross-domain-policy>  
       <site-control permitted-cross-domain-policies="all"/>  
       <allow-access-from domain="*" to-ports="*"/>
       </cross-domain-policy>
   tmpsocket.writeUTFBytes(xml.toString());
   tmpsocket.flush();
   log("发送策略文件到:"+xml.toString()+tmpsocket.remoteAddress+":"+tmpsocket.remotePort)

  //关掉
   tmpsocket.close();
 }
  //显示消息;
 protected function log(str:String):void{
   tmsg.appendText(str+"\n");
 }
 ]]>
   </fx:Script>
 <s:TextArea id="tmsg" x="48" y="11" editable="false" enabled="true"/>
</s:WindowedApplication>

 以下是web客户端源代码:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
      xmlns:s="library://ns.adobe.com/flex/spark"
      xmlns:mx="library://ns.adobe.com/flex/mx"
      width="500" height="400" minWidth="500" minHeight="500">
 
 <fx:Script>
  <![CDATA[
   import flash.events.*;
   import flash.net.Socket;
   import flash.utils.ByteArray;
   
   
   private var localIP:String="192.168.1.253";
   private var localPort:int=8888;
   private var socket:Socket;
   
   
   protected function bt_conn_clickHandler(event:MouseEvent):void
   {   socket=new Socket();
    socket.connect(localIP,localPort);
    socket.addEventListener(Event.CONNECT,onconnect);
    socket.addEventListener(IOErrorEvent.IO_ERROR,onError);
    socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onseError);
    socket.addEventListener(ProgressEvent.SOCKET_DATA,onData);
   }
   private function onconnect(e:Event):void{
    log("连接成功");
    
   }
   
   private function onError(e:IOErrorEvent):void{
    log("连接失败,服务器没打开!")
   }
   private function onseError(e:SecurityErrorEvent):void{
    log("连接失败,安全错误"+e.text)
   }
   //按钮发送
   protected function bt_send_clickHandler(event:MouseEvent):void
   {   
    sendmsg()
   }
   //接收到消息
   protected function onData(e:ProgressEvent):void{
    var ba:ByteArray=new ByteArray()
    var tmpsocket:Socket=e.target as Socket;
    tmpsocket.readBytes(ba,0,tmpsocket.bytesAvailable);
    log(ba.toString());
    
    
   }
   //发送消息;
   private function sendmsg():void{
    if(text_input.text!=""){
     socket.writeUTFBytes(text_input.text)
     socket.flush();
    
     text_input.text="";
    }else{
     log("不能发送空消息");
    } 
   }
   //显示消息
   private function log(str:String):void{
    text_msg.appendText(str+"\n")
   }
   
  ]]>
 </fx:Script>
 
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <s:Button id="bt_conn" x="10" y="348" label="连接" click="bt_conn_clickHandler(event)"/>
 <s:Button id="bt_send" x="381" y="352" label="发送" click="bt_send_clickHandler(event)"/>
 <s:TextInput id="text_input" x="122" y="319" width="251" height="54" enabled="true"
     enter="sendmsg()" prompt="输入消息"/>
 <s:TextArea id="text_msg" x="121" y="93" width="209" height="192" editable="false"
    enabled="true"/>
</s:Application>

AIR serverSocket服务端源代码:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:mx="library://ns.adobe.com/flex/mx"
        width="500" height="500">
 
 <fx:Script>
  <![CDATA[
   import flash.events.ServerSocketConnectEvent;
   import flash.net.ServerSocket;
   import flash.net.Socket;
   import flash.utils.ByteArray;
   
   
   
   private var serverSocket:ServerSocket;
   private var localIP:String="192.168.1.253";
   private var localPort:int=8888;
   private var clientList:Array=[];
  
   
   protected function bt_bind_clickHandler(event:MouseEvent):void
   {  
    serverSocket = new ServerSocket();
    serverSocket.bind(localPort,localIP);
    serverSocket.addEventListener(ServerSocketConnectEvent.CONNECT, onConnect );
    serverSocket.listen();
    log("绑定到:"+serverSocket.localAddress+":"+serverSocket.localPort);
   }
      
   protected function onConnect(e:ServerSocketConnectEvent):void{
    var tmpsocket:Socket=e.socket
    
    clientList.push(tmpsocket);
    tmpsocket.addEventListener(Event.CLOSE,onClose);
    tmpsocket.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);
    tmpsocket.writeUTFBytes("服务器消息:你已连接到服务器") 
    tmpsocket.flush();
    log("有新连接"+e.socket.remoteAddress+":"+e.socket.remotePort);
    }
   
   
   protected function onClose(e:Event):void{
    for (var clt:int=0;clt<clientList.length;clt++){
     if(clientList[clt].remoteAddress==e.target.remoteAddress){
      clientList.splice(clt,1); 
     }
    }
         
     log(e.target.remoteAddress+"断开") 
        
   }
   
   
   protected function onSocketData(e:ProgressEvent):void{
    var tmpsocket:Socket=e.target as Socket;
       var ba:ByteArray=new ByteArray()
         tmpsocket.readBytes(ba,0,e.target.bytesAvailable)
    var msg:String=ba.toString();
    if(msg.indexOf("<policy-file-request/>")>-1){
     log("不安全的客户端");
     
    }else{
          for each(var clt:Socket in clientList){
           clt.writeUTFBytes(tmpsocket.remoteAddress+":"+tmpsocket.remotePort+"消息:"+msg);
           clt.flush();
      
          }
        
       log("收到"+tmpsocket.remoteAddress+"消息:"+msg);   
    }
       
   }
   
   protected function bt_send_clickHandler(event:Event):void
   {
    sendmsg()
   }
   private function sendmsg():void{
       if(clientList.length>0){
         for each(var clt:Socket in clientList){
     
      clt.writeUTFBytes("服务器消息:"+text_send.text);
      clt.flush();
      log("消息已发送:"+clt.remoteAddress+":"+text_send.text);
     
         } 
    
       }else{
            log("当前无连接!")
         }
    text_send.text="";
   }
   protected function log(str:String):void{
    tr.appendText(str+"\n");
   }
  ]]>
 </fx:Script>
 
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <s:Button id="bt_bind" x="36" y="78" label="创建服务器" click="bt_bind_clickHandler(event)"/>
 <s:TextArea id="tr" x="41" y="124" width="243" height="196" contentBackgroundAlpha="0.73"
    editable="false" enabled="true"/>
 <s:Button id="bt_send" x="319" y="385" width="52" label="发送" click="bt_send_clickHandler(event)"/>
 <s:TextInput id="text_send" x="64" y="352" width="222" height="54" enabled="true" enter="sendmsg()"/>
 
 
</s:WindowedApplication>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值