zoukankan      html  css  js  c++  java
  • zmqSocket 使用和相关java后台准备

    zmqSocket.as 源码地址: http://zmqsocket-as.googlecode.com/svn/

    zmqSocket.js 源码地址: http://zmqsocket-js.googlecode.com/svn/

    zmqSocket.as是通过flex自带的socket在前端实现和后台消息通讯的一个简单类库,本来想简单配置下zmqSocket的使用,结果发现各种限制各种问题,整理出最后的使用规范和注意事项如下:

    首先关于后台(小弟使用java编写的后台,其他语言这里仅供参考):

    1、首先是跨域文件的获取,flex默认回去端口843寻找垮与文件,发送请求"<policy-file-request/>",并希望获得类似下列格式的跨域许可文件。

    <?xml version="1.0"?>  
    <cross-domain-policy>  
    <site-control permitted-cross-domain-policies="all"/>  
    <allow-access-from domain="IP地址或*" to-ports="socket打开的端口" />  
    </cross-domain-policy>  
    

      所以后台服务最好提供这样一个端口来专门负责处理

      另外的一个解决方式是在客户端直接使用Security.loadPolicyFile(url); ,从指定的url去获取垮与文件。

    关于跨域的内容可参考http://livedocs.adobe.com/flash/9.0_cn/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002106.html

    2、关于服务端设置,因为socket是以二进制字节流传输信息的,所以要求服务端也应该是针字节流进行解析(xmlSocket貌似没有这样的问题,后面测测再补充下,如果大家有其他方案也可以告知我下,互相学习)。

          *****服务端采用的方式,通过读取二进制数组,并将二进制数组接写成字符转来做最终的转义,写入的时候也是直接写入二进制字符串

    附上一个java端实现许可文件提供的服务以供参考:

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class FlexServer2 {
    	public static void main(String args[]) {
    		try {
    			DataInputStream din;
    			DataOutputStream dout;
    
    			ServerSocket flexServer = new ServerSocket(843);
    
    			while (true) {
    				Socket client = flexServer.accept();
    				din = new DataInputStream(client.getInputStream());
    				dout = new DataOutputStream(client.getOutputStream());
    
    				String s;
    				String backFile = "<?xml version="1.0"?>"
    						+ "<cross-domain-policy>"
    						+ "<site-control permitted-cross-domain-policies="all"/>"
    						+ "<allow-access-from domain="*" to-ports="*" />"
    						+ "</cross-domain-policy>";
    
    				// 设置一个长度空间的二进制数组来获取客户端信息
    				byte[] backBytes = backFile.getBytes("utf-8");
    				while (true) {
    					byte[] b = new byte[2048];
    					int length = din.read(b, 0, b.length);
    
    					if (length != -1) {
    						s = new String(b, 0, length);
    						System.out.println("843读到的信息:" + s);
    
    						if (s.equals("<policy-file-request/>")) {
    							dout.write(backBytes);
    							dout.flush();
    						} else {
    							break;
    						}
    					}
    				}
    				din.close();
    				dout.close();
    				client.close();
    			}
    
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    	}
    }
    

    服务端需要注意的也就这两点了,在客户端直接使用zmqSocket也有些严格要求的地方,细列如下:

    客户端注意实现:

    1、信息接收,提供类似事件回调的方式。 这点不同于习以为常的java或者c++代码,通过一个线程等待去轮询获取接收信息。(因为是flash是单线程的,如果等待意味着其他事都做不了了)。

       比如直接使用socket,接收信息的办法是在  ProgressEvent.SOCKET_DATA 事件中去 判断bytesAvailable 并调用类似socket.readUTFBytes(bytesAvailable)的方法去获取信息。

    关于直接使用socket的Demo请直接查看 Flex 4.0的API文档中的示例,很简单。

    2、补充1. 关于zmqSocket中,内部添加一个关于信息的接收栈,只有当信息接收到足够多内容才会触发 Message 事件,(保留了跟socket默认的事件回调风格)也只有在这个时候嗲用recv()方法才能获取到信息。否则在下一次消息来临之后则会覆盖之前的信息。

        关于这点要说明的是,当服务端信息过短的时候,是可能不会触发Message事件的,即意味着客户端可能没法立刻通过事件回调读取信息(关于这块应该是有可设置选项的,待研究吧)

    给出一个直接使用zmqSocket.as的示范代码,来源于zmqSocket的官方测试代码:

    <?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" minWidth="955" minHeight="600"
    			   creationComplete="initSocket()"
    			   >
    	<fx:Script>
    		<![CDATA[
    			
    			private function initSocket():void
    			{
    				var input: TextField = new TextField;
    				input.type = TextFieldType.INPUT;
    				input.background = true;
    				input.border = true;
    				input.width = 350;
    				input.height = 350;
    				ucom.addChild(input);
    				input.appendText ("Starting
    ");
    				
    				try
    				{
    					var socket: ZmqSocket = new ZmqSocket ();
    				}
    				catch (e: Error)
    				{
    					input.appendText ("Error: " + e.toString ());
    					return;
    				}
    				
    				socket.addEventListener (ZmqSocket.OPEN, function (e: Event)
    				{
    					input.appendText ("opened
    ");
    					socket.send (["", "Test"]);
    				});
    				
    				socket.addEventListener (ZmqSocket.MESSAGE, function (e: Event)
    				{
    					var msg: Array = socket.recv ();
    					input.appendText (msg.length + "
    ");
    					if (msg.length > 1)
    						input.appendText (msg[1] + "
    ");
    					
    					socket.send (["", "Test"]);
    				});
    				
    				socket.addEventListener (Event.CLOSE, function (e: Event)
    				{
    					input.appendText ("closed
    ");
    				});
    				
    				socket.addEventListener (IOErrorEvent.IO_ERROR, function (e: IOErrorEvent)
    				{
    					input.appendText (e.toString ()+"
    ");
    				});
    				
    				socket.addEventListener (SecurityErrorEvent.SECURITY_ERROR, function (e: SecurityErrorEvent)
    				{
    					input.appendText (e.toString ()+"
    ");
    				});
    				
    				socket.connect ("localhost", 2000);
    			}
    			
    		]]>
    	</fx:Script>
    	<s:layout>
    		<s:BasicLayout/>
    	</s:layout>
    	<mx:UIComponent id="ucom"/>
    	<fx:Declarations>
    		<!-- 将非可视元素(例如服务、值对象)放在此处 -->
    	</fx:Declarations>
    </s:Application>
    

    3、追加3, 问题仍然是关于zmqSocket.as源码的。小弟下到的版本在信息发送时没有socket.flush() 这行代码的调用,导致服务端一直无法获得信息。补充后测试OK

        注:这个在源码svn的的提交记录中是有过修改的,不知道为什么小弟这个版本没有,提醒大家遇到同样的问题可以自己修改下,重新编译swf,免得纠结...

    总结,目前发现的问题就是上述了, 都是很小的细节,但很让人恼火..... 希望对大家有所帮助:

    最后,简单实用as貌似不会太多,我们看看直接使用zmqSocket.js的,这里是通过客户端js与as的交互,来实现第一个普通网页的请求处理。

    这里直接使用官方获取到的示例代码。zmqSocket和zmqSocketMain源码重新编译,生成新的zmqSocketMain.swf文件。配合上述的服务端代码测试,OK!!!O(∩_∩)O~

    注意:发现的小问题,在本地直接双击打开网页的时候可能会有ExternalInterface.calll方法跨域错误。  解决方案1:修改flashPlayerTrust文件下的配置。2:发布网页通过ip地址访问测试

    示范代码如下:

    //////////file  zmqSocket.js
    (function() 
    {
        // Check if module is already initialized.
        if (window.ZmqSocket)
            return;
    
        // Constructor. You may pass socket identity here.
        ZmqSocket = function(identity) 
        {
            this.fd = ZmqSocket.__nextFd++;
            ZmqSocket.__sockets[this.fd] = this;
            
            this.identity = identity;
            this.state = ZmqSocket.CONNECTING;
            this.onopen = function() {
            };
            this.onmessage = function() {
            };
            this.onerror = function(msg) {
            };
            this.onclose = function() {
            };
            
            var athis = this;
            ZmqSocket.__addTask(function() 
            {
                ZmqSocket.__flash.create(athis.fd, athis.identity);
            });
        };
        
        ZmqSocket.__sockets = [];
        ZmqSocket.__tasks = [];
        ZmqSocket.__nextFd = 0;
        ZmqSocket.__flash = null;
        
        ZmqSocket.CONNECTING = 1;
        ZmqSocket.OPEN = 2;
        ZmqSocket.CLOSING = 3;
    
        // Called by Flash when it's ready.
        ZmqSocket.__onFlashReady = function() 
        {
            if (navigator.appName.indexOf("Microsoft") != -1)
                ZmqSocket.__flash = window["ZmqSocketFlash"];
            else
                ZmqSocket.__flash = document["ZmqSocketFlash"];
    
            // Make it later to avoid recursion.
            ZmqSocket.__later(function() 
            {
                for (var i = 0; i < ZmqSocket.__tasks.length; i++)
                    ZmqSocket.__tasks[i]();
            });
        };
    
        // Used to make calls in a separate event handler to avoid
        // recursive calls to Flash - recursion is not supported by many browsers.
        ZmqSocket.__later = function(task) 
        {
            var to = setTimeout(function() {
                clearTimeout(to);
                task();
            }, 0);
        }
    
        // Called by Flash to find out if JS is ready.
        ZmqSocket.__isJSReady = function() {
            return true;
        };
    
        // Called when we are not sure that flash is ready.
        ZmqSocket.__addTask = function(task) 
        {
            if (ZmqSocket.__flash)
                task();
            else
                ZmqSocket.__tasks.push(task);
        }
        
        ZmqSocket.prototype.connect = function(host, port) 
        {
            var athis = this;
            ZmqSocket.__addTask(function() 
            {
                ZmqSocket.__flash.connect(athis.fd, host, port);
            });
        }
        
        ZmqSocket.prototype.close = function() 
        {
            this.state = ZmqSocket.CLOSING;
            var athis = this;
            ZmqSocket.__addTask(function() 
            {
                alert('before');
                ZmqSocket.__flash.close(athis.fd);
                alert('after');
            });
        }
        
        ZmqSocket.prototype.available = function() 
        {
            if (this.state != ZmqSocket.OPEN)
                throw "Invalid state, socket must be connected!";
            
            return ZmqSocket.__flash.available(this.fd);
        }
        
        ZmqSocket.prototype.recv = function() 
        {
            if (this.state != ZmqSocket.OPEN)
                throw "Invalid state, socket must be connected!";
            
            return ZmqSocket.__flash.recv(this.fd);
        }
        
        ZmqSocket.prototype.send = function(msg) 
        {
            if (this.state != ZmqSocket.OPEN)
                throw "Invalid state, socket must be connected!";
            
            return ZmqSocket.__flash.send(this.fd, msg);
        }
        
        ZmqSocket.__onopen = function(fd) 
        {
            // Avoiding recursion
            ZmqSocket.__later(function() 
            {
                ZmqSocket.__sockets[fd].state = ZmqSocket.OPEN;
                ZmqSocket.__sockets[fd].onopen();
            });
        }
        
        ZmqSocket.__onmessage = function(fd) 
        {
            // Avoiding recursion
            ZmqSocket.__later(function() {
                ZmqSocket.__sockets[fd].onmessage();
            });
        }
        
        ZmqSocket.__onerror = function(fd, msg) 
        {
            // Avoiding recursion
            ZmqSocket.__later(function() {
                ZmqSocket.__sockets[fd].onerror(msg);
            });
        }
        
        ZmqSocket.__onclose = function(fd) 
        {
            // Avoiding recursion
            ZmqSocket.__later(function() {
                ZmqSocket.__sockets[fd].onclose();
            });
        }
    
    })();
    

     

    /////////file Test.html
    
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>ZmqSocket.js</title>
    <script language="JavaScript" src='ZmqSocket.js'>
    </script>
    </head>
    <body>
     
    <script language="JavaScript">
    
    var socket = new ZmqSocket();
    var ready = false;
    
    socket.onopen = function() {
        ready = true;
    };
    socket.onmessage = function() {
        if (socket.available()) {
            var m = socket.recv();
            alert(m);
        } else {
            alert('Assertion failure!');
        }
    };
    socket.onclose = function() {
        alert('close');
    };
    socket.onerror = function(msg) {
        alert(msg);
    };
    
    socket.connect("localhost", 2000);
    </script>
     
    <input type='text' id='in' />
    <input type='submit' value='Send' onclick='if (!ready) return; var t = document.getElementById("in").value; socket.send (["", t]); ' />
     
    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
     id="ZmqSocketFlash" width="0" height="0"
     codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
     <param name="movie" value="ZmqSocketMain.swf" />
     <param name="allowScriptAccess" value="sameDomain" />
     <embed src="ZmqSocketMain.swf" quality="high" 
      width="0" height="0" name="ZmqSocketFlash" align="middle"
      play="true" loop="false" allowScriptAccess="sameDomain"
      type="application/x-shockwave-flash"
      pluginspage="http://www.macromedia.com/go/getflashplayer">
     </embed>
    </object>
    
    </body>
    </html>
     
    

      

     

  • 相关阅读:
    python之路---23 模块 os sys pickle json
    Fiddler抓包【7】_次要功能和第三方插件
    Fiddler抓包【6】_Fiddler Script
    Fiddler抓包【5】_Fiddler过滤
    Fiddler抓包【4】_重定向AutoResponder
    Fiddler抓包【3】_设置断点修改
    Fiddler抓包【2】_捕获设置
    Fiddler抓包【1】_介绍及界面概述
    CSS常见兼容问题以及解决办法
    webpack入门文档教程
  • 原文地址:https://www.cnblogs.com/xignzou/p/3207832.html
Copyright © 2011-2022 走看看