结果:
从github上的 web-socket-js (socket.io好像也是用这个做的他们的flash替代传输方式)改过来的。不过值得注意的是里面的flash websocket代理文件,文件实在是很大,有174k
很好奇,就反编译看下,
是flex做的,这点很不喜欢,因为我没有flex builder也不想因为去改代码重新装一个,然后mx包下面的是flex的组件,com包下是adobe封装的socket和两个加密包 .
最下面那个包才是最主要的,代码不是很复杂,就是利用actionscript3的socket,与那边服务端socket握手,传递消息,不过区别是,在connect的时候要把header封装成websocket的样子
这也是flash模拟websocket的原理。事实上,直接用flash的socket就可以完成与服务端的双向信息传递,不过缺点是需要在服务端的socket代码写很多其他的代码,比如多线程,信息解析等,直接用websocket就不用写那些多余的代码了。
我花了点时间把源码里面和加密有关的代码都注释掉,加密的代码都是和wss(类似于https)有关的,用flash编译了一下,主要就是把mx包加到flash编译里面,flex是臃肿版的flash,结果大小只有20k!原来加密让文件大太多了!
websocket.js
define("websocket", function() { (function() { if (window.WEB_SOCKET_FORCE_FLASH) { // Keeps going. } else if (window.WebSocket) { return; } else if (window.MozWebSocket) { // Firefox. window.WebSocket = MozWebSocket; return; } var logger; if (window.WEB_SOCKET_LOGGER) { logger = WEB_SOCKET_LOGGER; } else if (window.console && window.console.log && window.console.error) { logger = window.console; } else { logger = {log: function(){ }, error: function(){ }}; } window.WebSocket = function(url, protocols, proxyHost, proxyPort, headers) { var self = this; self.__id = WebSocket.__nextId++; WebSocket.__instances[self.__id] = self; self.readyState = WebSocket.CONNECTING; self.bufferedAmount = 0; self.__events = {}; if (!protocols) { protocols = []; } else if (typeof protocols == "string") { protocols = [protocols]; } self.__createTask = setTimeout(function() { WebSocket.__addTask(function() { self.__createTask = null; WebSocket.__flash.create( self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null); }); }, 0); }; WebSocket.prototype.send = function(data) { if (this.readyState == WebSocket.CONNECTING) { throw "INVALID_STATE_ERR: Web Socket connection has not been established"; } var result = WebSocket.__flash.send(this.__id, encodeURIComponent(data)); if (result < 0) { // success return true; } else { this.bufferedAmount += result; return false; } }; WebSocket.prototype.close = function() { if (this.__createTask) { clearTimeout(this.__createTask); this.__createTask = null; this.readyState = WebSocket.CLOSED; return; } if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) { return; } this.readyState = WebSocket.CLOSING; WebSocket.__flash.close(this.__id); }; WebSocket.prototype.dispatchEvent = function(event) { var events = this.__events[event.type] || []; for (var i = 0; i < events.length; ++i) { events[i](event); } var handler = this["on" + event.type]; if (handler) handler.apply(this, [event]); }; WebSocket.prototype.__handleEvent = function(flashEvent) { if ("readyState" in flashEvent) { this.readyState = flashEvent.readyState; } if ("protocol" in flashEvent) { this.protocol = flashEvent.protocol; } var jsEvent; if (flashEvent.type == "open" || flashEvent.type == "error") { jsEvent = this.__createSimpleEvent(flashEvent.type); } else if (flashEvent.type == "close") { jsEvent = this.__createSimpleEvent("close"); jsEvent.wasClean = flashEvent.wasClean ? true : false; jsEvent.code = flashEvent.code; jsEvent.reason = flashEvent.reason; } else if (flashEvent.type == "message") { var data = decodeURIComponent(flashEvent.message); jsEvent = this.__createMessageEvent("message", data); } else { throw "unknown event type: " + flashEvent.type; } this.dispatchEvent(jsEvent); }; WebSocket.prototype.__createSimpleEvent = function(type) { if (document.createEvent && window.Event) { var event = document.createEvent("Event"); event.initEvent(type, false, false); return event; } else { return {type: type, bubbles: false, cancelable: false}; } }; WebSocket.prototype.__createMessageEvent = function(type, data) { if (window.MessageEvent && typeof(MessageEvent) == "function" && !window.opera) { return new MessageEvent("message", { "view": window, "bubbles": false, "cancelable": false, "data": data }); } else if (document.createEvent && window.MessageEvent && !window.opera) { var event = document.createEvent("MessageEvent"); event.initMessageEvent("message", false, false, data, null, null, window, null); return event; } else { return {type: type, data: data, bubbles: false, cancelable: false}; } }; WebSocket.CONNECTING = 0; WebSocket.OPEN = 1; WebSocket.CLOSING = 2; WebSocket.CLOSED = 3; WebSocket.__isFlashImplementation = true; WebSocket.__initialized = false; WebSocket.__flash = null; WebSocket.__instances = {}; WebSocket.__tasks = []; WebSocket.__nextId = 0; WebSocket.loadFlashPolicyFile = function(url){ WebSocket.__addTask(function() { WebSocket.__flash.loadManualPolicyFile(url); }); }; WebSocket.__initialize = function() { if (WebSocket.__initialized) return; WebSocket.__initialized = true; if (WebSocket.__swfLocation) { window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation; } }; WebSocket.__onFlashInitialized = function() { setTimeout(function() { WebSocket.__flash =main.get_flash_obj("webSocketFlash"); WebSocket.__flash.setCallerUrl(location.href); WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG); for (var i = 0; i < WebSocket.__tasks.length; ++i) { WebSocket.__tasks[i](); } WebSocket.__tasks = []; }, 0); }; WebSocket.__onFlashEvent = function() { setTimeout(function() { try { var events = WebSocket.__flash.receiveEvents(); for (var i = 0; i < events.length; ++i) { WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]); } } catch (e) { logger.error(e); } }, 0); return true; }; WebSocket.__log = function(message) { logger.log(decodeURIComponent(message)); }; WebSocket.__error = function(message) { logger.error(decodeURIComponent(message)); }; WebSocket.__addTask = function(task) { if (WebSocket.__flash) { task(); } else { WebSocket.__tasks.push(task); } }; })(); return WebSocket; });
websocket_main.js
require(['html5/websocket','avalon-min'],function(WebSocket,avalon){ var $=function(id){ return document.getElementById(id); }; WEB_SOCKET_DEBUG = true; var ws; ws = new WebSocket("ws://localhost:8888/new-msg/socket"); ws.onopen = function() { output("onopen"); }; ws.onmessage = function(e) { output("onmessage: " + e.data); }; ws.onclose = function() { output("onclose"); }; ws.onerror = function() { output("onerror"); }; avalon.bind($('send'),'click',function(){ var input = $("input1"); ws.send(input.value); output("send: " + input.value); input.value = ""; input.focus(); }); avalon.bind($('close'),'click',function(){ ws.close(); }); function output(str) { var log = document.getElementById("log"); var escaped = str.replace(/&/, "&").replace(/</, "<") .replace(/>/, ">").replace(/"/, """); // " log.innerHTML = escaped + "<br>" + log.innerHTML; } });HTML:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script src="http://localhost/twitter/js/libs/seed-min.js"></script> <script type="text/javascript" src="http://localhost/twitter/js/libs/flash_embed.js"></script> <script src="http://localhost/twitter/js/main.js" type="text/javascript"></script> </head> <body> <input type="text" id="input1"> <input type="submit" value="Send" id='send'> <button id='close'>close</button> <div id="log"></div> <div id='a' style='width: 1px; height: 1px;'></div> <script type="text/javascript"> flash_object.embedSWF('http://localhost:8888/swf/WebSocketMain.swf', 'a', 'webSocketFlash', '100%', '100%'); </script> <script type="text/javascript" src='http://localhost/twitter/js/libs/html5/websocket_main.js'></script> </body> </html>
下面很重要,在运行前一定要开启服务端(python)的socket
import socket import time from threading import Thread class returnCrossDomain(Thread): def __init__(self,connection): Thread.__init__(self) self.con = connection def run(self): clientData = self.con.recv(1024) xmlData = '''<?xml version="1.0" encoding="utf-8"?>''' xmlData += '''<cross-domain-policy><policy-file-request/>''' xmlData += '''<allow-access-from domain="*" to-ports="*" />''' xmlData += '''</cross-domain-policy>\0''' try: self.con.send(xmlData) except Excepiton,e: pass self.con.close() def main(): sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.bind(('localhost',843)) sock.listen(10000000) print 'socket' while True: try: connection,address = sock.accept() returnCrossDomain(connection).start() except: time.sleep(1) if __name__=="__main__": main()
服务端用python的tornado写的,也一样在运行前开启tornado
# -*- coding: utf-8 -*- import base import tornado.websocket def send_message(message): for handler in ChatSocketHandler.socket_handlers: handler.write_message(message) class ChatSocketHandler(tornado.websocket.WebSocketHandler): socket_handlers = set() def open(self): ChatSocketHandler.socket_handlers.add(self) print 'websocket' send_message('A new user has entered the chat room.') def on_close(self): ChatSocketHandler.socket_handlers.remove(self) print 'websocket close' send_message('A user has left the chat room.') def on_message(self, message): print 'message:'+message send_message(message)
tornado很好的封装了websocket,用起来很简单,加上flash模拟websocket兼容不支持websocket的浏览器,这样可以完美的利用高效的websocket.
如果嫌弃flash的话,还是用ajax长连接,tornado很好的支持ajax长连接,性能很好.
socket.io也是个不错的选择,提供了多种传输方案。
WebSocketMain.swf文件及源码见附件
相关推荐
然而,WebSocket协议是基于HTML5的,因此在一些老版本的浏览器,特别是像IE8这样的旧版Internet Explorer上,原生不支持WebSocket。 要解决WebSocket在IE8上的兼容性问题,我们需要借助一些第三方库和技术。这里...
IE8并不原生支持WebSocket,因为WebSocket协议是在HTML5规范中定义的,而IE8发布时HTML5还在发展初期。为了解决这个问题,开发者通常会使用一些 polyfill 库,比如`web-socket-js-master`这个压缩包可能包含的就是一...
"WebSocketDemo2支持ie浏览器"这个项目旨在实现一个WebSocket应用,不仅适用于现代浏览器如Firefox和Chrome,而且能够兼容较旧版本的Internet Explorer(至少IE9)。 WebSocket协议的设计目的是为了解决HTTP协议的...
然而,WebSocket协议在早期的Internet Explorer浏览器(即IE6、IE7和IE8)中并未得到支持,因为这些浏览器版本相对较老,不包含原生的WebSocket API。 为了使WebSocket兼容IE6、IE7和IE8,开发者通常会借助Adobe ...
### ie9以下老浏览器不支持HTML5的解决方法 在Web开发领域,兼容性问题一直是个头疼的问题,尤其是在处理老旧浏览器如Internet Explorer(IE)时。对于那些使用IE9及以下版本的老用户来说,由于这些浏览器对HTML5的...
8. **WebSocket服务器**:WebSocket服务器端通常使用专门的库或框架来创建,例如Node.js的ws库,Java的Jetty或Tomcat,或者Python的Tornado。这些服务器需要支持WebSocket协议,并能处理Flash Socket API发出的连接...
从安卓到苹果,从delphi7-delphi XE8 统统支持,源码!源码!源码!, 有客户端有服务端,这是一个经典的浏览器与delphi的Socket通讯! 谷歌,火狐,IE通通有演示.我编译了一个服务器例子.里面含全部源代码! 注意,解压密码为:1...
标题 "教你一招让你的IE 6/7/8/9/x都支持HTML5" 描述了一种方法,旨在使旧版本的 Internet Explorer(IE 6、7、8、9 和 x)能够支持现代的 HTML5 标准。在那个时期,IE 浏览器对新标准的支持相对滞后,这给开发者...
3. html5shiv:html5shiv是一个小型的JavaScript库,专为了解决IE6-IE8不识别HTML5新标签的问题。它允许在这些老版本的IE浏览器中应用CSS样式到H5元素。 4. 使用jQuery或其他JavaScript框架:某些JavaScript框架如...
在现代浏览器中,WebSocket 已经得到了广泛支持,但遗憾的是,早期版本的 Internet Explorer(如 IE6 和 IE9)并不支持这个技术。由于 WebSocket 的强大功能,开发者们自然不想因为浏览器的兼容性问题而放弃使用它。...
在WebSocket尚未被所有浏览器原生支持的时代,Flash通过ActionScript 3的Socket API实现了WebSocket的兼容层,使得开发者可以通过Flash Player在这些旧版浏览器上实现WebSocket通信。 要实现这个功能,你需要创建一...
在给定的标签中提到,WebSocket在IE8和IE9这样的老版本浏览器中也是支持的,这意味着开发者可以为广泛的用户群体提供实时通信功能。 WebSocket的实现通常涉及以下几个步骤: 1. **初始化连接**:客户端通过`ws://`...
一个完全用HTML5实现的网络...(注:该程序在火狐10.0、11.0版本、谷歌15.0、17.0版本的浏览器上测试过了,其他较老版本的浏览器可能不支持WebSocket,IE内核的浏览器就别去试了,当前微软明确表示不支持WebSocket...)
作为HTML5的一个重要新特性,WebSocket 规范的目标是在浏览器中实现和服务器端双向通信.双向通信可以拓展浏览器上的应用类型,例如实时的数据推送(股票行情),游戏,聊天/im 等. 现已支持WebSocket的浏览器有: ...
可惜现在不是所有浏览器都支持HTML5,本例是对TOMCAT7.0.32自带的WebSocket功能展示,一个非常简单的聊天室。 代码说明 1、因为本例只做功能展示,所以使用最为精简的代码,只写了2个类和一个JSP,另外使用到TOMCAT7...
WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例如Chrome,Safari,Firefox,Opera,IE等等,对该协议支持最早的应该是chrome,从chrome12就已经开始支持,随着协议草案的不断变化,各个...
在这个“可用的WebSocketDemo”中,我们看到的是一个用Java编写的WebSocket服务器端应用,它兼容火狐和谷歌浏览器,但不支持IE9,对于IE10的支持情况未做测试。 WebSocket协议的引入是为了弥补HTTP协议在实时性上的...
在这个"WebSocket聊天室demo"项目中,开发者手工编写了代码,确保了其原创性和适应性,已经在IE11、Firefox和Chrome等主流浏览器上进行了兼容性测试并成功运行。 WebSocket协议的核心概念: 1. **握手(Handshake)...
5. 兼容IE低版本:对于不支持WebSocket的IE浏览器,Netty-socketio会自动切换到长轮询模式。长轮询是一种HTTP持久连接的方式,服务器在接收到请求后不会立即返回,而是等待有新的数据时才发送响应,从而达到实时通信...