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

2024-01-05 19:08

本文主要是介绍用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>


这篇关于用as3 serverSocket 做服务端,实现web客户端的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/573869

相关文章

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库