对不支持原生html5 websocket的浏览器进行兼容

结果:

  

  转载请注明:TheViper

  从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的原理。

我花了点时间把源码里面和加密有关的代码都注释掉,加密的代码都是和wss(类似于https)有关的,用flash编译了一下,主要就是把mx包加到flash编译里面,flex是臃肿版的flash,结果大小只有20k!原来加密让文件大太多了!

websocket.js

  1 define("websocket", function() {
  2 (function() {
  3   if (window.WEB_SOCKET_FORCE_FLASH) {
  4     // Keeps going.
  5   }
  6   else if (window.WebSocket) {
  7     return;
  8   } else if (window.MozWebSocket) {
  9     // Firefox.
 10     window.WebSocket = MozWebSocket;
 11     return;
 12   }
 13   var logger;
 14   if (window.WEB_SOCKET_LOGGER) {
 15     logger = WEB_SOCKET_LOGGER;
 16   } else if (window.console && window.console.log && window.console.error) {
 17     logger = window.console;
 18   } else {
 19     logger = {log: function(){ }, error: function(){ }};
 20   }
 21   window.WebSocket = function(url, protocols, proxyHost, proxyPort, headers) {
 22     var self = this;
 23     self.__id = WebSocket.__nextId++;
 24     WebSocket.__instances[self.__id] = self;
 25     self.readyState = WebSocket.CONNECTING;
 26     self.bufferedAmount = 0;
 27     self.__events = {};
 28     if (!protocols) {
 29       protocols = [];
 30     } else if (typeof protocols == "string") {
 31       protocols = [protocols];
 32     }
 33     self.__createTask = setTimeout(function() {
 34       WebSocket.__addTask(function() {
 35         self.__createTask = null;
 36         WebSocket.__flash.create(
 37             self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null);
 38       });
 39     }, 0);
 40   };
 41   WebSocket.prototype.send = function(data) {
 42     if (this.readyState == WebSocket.CONNECTING) {
 43       throw "INVALID_STATE_ERR: Web Socket connection has not been established";
 44     }
 45     var result = WebSocket.__flash.send(this.__id, encodeURIComponent(data));
 46     if (result < 0) { // success
 47       return true;
 48     } else {
 49       this.bufferedAmount += result;
 50       return false;
 51     }
 52   };
 53   WebSocket.prototype.close = function() {
 54     if (this.__createTask) {
 55       clearTimeout(this.__createTask);
 56       this.__createTask = null;
 57       this.readyState = WebSocket.CLOSED;
 58       return;
 59     }
 60     if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) {
 61       return;
 62     }
 63     this.readyState = WebSocket.CLOSING;
 64     WebSocket.__flash.close(this.__id);
 65   };
 66   WebSocket.prototype.dispatchEvent = function(event) {
 67     var events = this.__events[event.type] || [];
 68     for (var i = 0; i < events.length; ++i) {
 69       events[i](event);
 70     }
 71     var handler = this["on" + event.type];
 72     if (handler) handler.apply(this, [event]);
 73   };
 74   WebSocket.prototype.__handleEvent = function(flashEvent) {
 75     if ("readyState" in flashEvent) {
 76       this.readyState = flashEvent.readyState;
 77     }
 78     if ("protocol" in flashEvent) {
 79       this.protocol = flashEvent.protocol;
 80     }
 81     var jsEvent;
 82     if (flashEvent.type == "open" || flashEvent.type == "error") {
 83       jsEvent = this.__createSimpleEvent(flashEvent.type);
 84     } else if (flashEvent.type == "close") {
 85       jsEvent = this.__createSimpleEvent("close");
 86       jsEvent.wasClean = flashEvent.wasClean ? true : false;
 87       jsEvent.code = flashEvent.code;
 88       jsEvent.reason = flashEvent.reason;
 89     } else if (flashEvent.type == "message") {
 90       var data = decodeURIComponent(flashEvent.message);
 91       jsEvent = this.__createMessageEvent("message", data);
 92     } else {
 93       throw "unknown event type: " + flashEvent.type;
 94     }
 95     this.dispatchEvent(jsEvent);
 96   };
 97   WebSocket.prototype.__createSimpleEvent = function(type) {
 98     if (document.createEvent && window.Event) {
 99       var event = document.createEvent("Event");
100       event.initEvent(type, false, false);
101       return event;
102     } else {
103       return {type: type, bubbles: false, cancelable: false};
104     }
105   };
106   WebSocket.prototype.__createMessageEvent = function(type, data) {
107     if (window.MessageEvent && typeof(MessageEvent) == "function" && !window.opera) {
108       return new MessageEvent("message", {
109         "view": window,
110         "bubbles": false,
111         "cancelable": false,
112         "data": data
113       });
114     } else if (document.createEvent && window.MessageEvent && !window.opera) {
115       var event = document.createEvent("MessageEvent");
116         event.initMessageEvent("message", false, false, data, null, null, window, null);
117       return event;
118     } else {
119       return {type: type, data: data, bubbles: false, cancelable: false};
120     }
121   };
122   WebSocket.CONNECTING = 0;
123   WebSocket.OPEN = 1;
124   WebSocket.CLOSING = 2;
125   WebSocket.CLOSED = 3;
126   WebSocket.__isFlashImplementation = true;
127   WebSocket.__initialized = false;
128   WebSocket.__flash = null;
129   WebSocket.__instances = {};
130   WebSocket.__tasks = [];
131   WebSocket.__nextId = 0;
132   WebSocket.loadFlashPolicyFile = function(url){
133     WebSocket.__addTask(function() {
134       WebSocket.__flash.loadManualPolicyFile(url);
135     });
136   };
137   WebSocket.__initialize = function() {
138     if (WebSocket.__initialized) return;
139     WebSocket.__initialized = true;
140     if (WebSocket.__swfLocation) {
141       window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;
142     }
143   };
144   WebSocket.__onFlashInitialized = function() {
145     setTimeout(function() {
146       WebSocket.__flash =main.get_flash_obj("webSocketFlash");
147       WebSocket.__flash.setCallerUrl(location.href);
148       WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG);
149       for (var i = 0; i < WebSocket.__tasks.length; ++i) {
150         WebSocket.__tasks[i]();
151       }
152       WebSocket.__tasks = [];
153     }, 0);
154   };
155   WebSocket.__onFlashEvent = function() {
156     setTimeout(function() {
157       try {
158         var events = WebSocket.__flash.receiveEvents();
159         for (var i = 0; i < events.length; ++i) {
160           WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]);
161         }
162       } catch (e) {
163         logger.error(e);
164       }
165     }, 0);
166     return true;
167   };
168   WebSocket.__log = function(message) {
169     logger.log(decodeURIComponent(message));
170   };
171   WebSocket.__error = function(message) {
172     logger.error(decodeURIComponent(message));
173   };
174   WebSocket.__addTask = function(task) {
175     if (WebSocket.__flash) {
176       task();
177     } else {
178       WebSocket.__tasks.push(task);
179     }
180   };
181 })();
182 return WebSocket;
183 });

websocket_main.js

 1 require([‘html5/websocket‘,‘avalon-min‘],function(WebSocket,avalon){
 2     var $=function(id){
 3         return document.getElementById(id);
 4     };
 5     WEB_SOCKET_DEBUG = true;
 6     var ws;
 7         ws = new WebSocket("ws://localhost:8888/new-msg/socket");
 8         ws.onopen = function() {
 9             output("onopen");
10         };
11         ws.onmessage = function(e) {
12             output("onmessage: " + e.data);
13         };
14         ws.onclose = function() {
15             output("onclose");
16         };
17         ws.onerror = function() {
18             output("onerror");
19         };
20     avalon.bind($(‘send‘),‘click‘,function(){
21             var input = $("input1");
22             ws.send(input.value);
23             output("send: " + input.value);
24             input.value = "";
25             input.focus();
26     });
27     avalon.bind($(‘close‘),‘click‘,function(){
28             ws.close();
29     });
30     function output(str) {
31         var log = document.getElementById("log");
32         var escaped = str.replace(/&/, "&amp;").replace(/</, "&lt;")
33                 .replace(/>/, "&gt;").replace(/"/, "&quot;"); // "
34         log.innerHTML = escaped + "<br>" + log.innerHTML;
35     }
36 });
 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 5 <title>Insert title here</title>
 6 <script src="http://localhost/twitter/js/libs/seed-min.js"></script>
 7 <script type="text/javascript"
 8     src="http://localhost/twitter/js/libs/flash_embed.js"></script>
 9 <script src="http://localhost/twitter/js/main.js" type="text/javascript"></script>
10 </head>
11 <body>
12     <input type="text" id="input1">
13     <input type="submit" value="Send" id=‘send‘>
14     <button id=‘close‘>close</button>
15     <div id="log"></div>
16     <div id=‘a‘ style=‘width: 1px; height: 1px;‘></div>
17     <script type="text/javascript">
18         flash_object.embedSWF(‘http://localhost:8888/swf/WebSocketMain.swf‘,
19                 ‘a‘, ‘webSocketFlash‘, ‘100%‘, ‘100%‘);
20     </script>
21     <script type="text/javascript"
22         src=‘http://localhost/twitter/js/libs/html5/websocket_main.js‘></script>
23 </body>
24 </html>

下面很重要,在运行前一定要开启服务端(python)的socket

 1 import socket
 2 import time
 3 from threading import Thread
 4
 5 class returnCrossDomain(Thread):
 6     def __init__(self,connection):
 7         Thread.__init__(self)
 8         self.con = connection
 9     def run(self):
10         clientData  = self.con.recv(1024)
11         xmlData  = ‘‘‘<?xml version="1.0" encoding="utf-8"?>‘‘‘
12         xmlData += ‘‘‘<cross-domain-policy><policy-file-request/>‘‘‘
13         xmlData += ‘‘‘<allow-access-from domain="*" to-ports="*" />‘‘‘
14     xmlData += ‘‘‘</cross-domain-policy>\0‘‘‘
15         try:
16             self.con.send(xmlData)
17         except Excepiton,e:
18             pass
19         self.con.close()
20 def main():
21     sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
22     sock.bind((‘localhost‘,843))
23     sock.listen(10000000)
24     print ‘socket‘
25     while True:
26         try:
27             connection,address = sock.accept()
28             returnCrossDomain(connection).start()
29         except:
30             time.sleep(1)
31
32 if __name__=="__main__":
33     main()

服务端用python的tornado写的,也一样在运行前开启tornado

 1 # -*- coding: utf-8 -*-
 2 import base
 3 import tornado.websocket
 4
 5 def send_message(message):
 6     for handler in ChatSocketHandler.socket_handlers:
 7         handler.write_message(message)
 8
 9 class ChatSocketHandler(tornado.websocket.WebSocketHandler):
10     socket_handlers = set()
11
12     def open(self):
13         ChatSocketHandler.socket_handlers.add(self)
14         print ‘websocket‘
15         send_message(‘A new user has entered the chat room.‘)
16
17     def on_close(self):
18         ChatSocketHandler.socket_handlers.remove(self)
19         print ‘websocket close‘
20         send_message(‘A user has left the chat room.‘)
21
22     def on_message(self, message):
23         print ‘message:‘+message
24         send_message(message)

tornado很好的封装了websocket,用起来很简单,加上flash模拟websocket兼容不支持websocket的浏览器,这样可以完美的利用高效的websocket

WebSocketMain.swf文件及源码:http://files.cnblogs.com/TheViper/flash_websocket.zip

时间: 2024-10-31 18:45:56

对不支持原生html5 websocket的浏览器进行兼容的相关文章

基于tomcat运行HTML5 WebSocket echo例子

一:概述 作为HTML5新特性之一的WebSocket组件,在实时性有一定要求的WEB应用开发中还是有一定用武之地,高版本的IE.Chrome.FF浏览器都支持Websocket,标准的Websocket通信是基于RFC6455实现服务器端与客户端握手与消息接发的.如果对Websocket通信不是太理解,可以查看RFC文档即可,简单说就是通过发送HTTP请求,实现双方握手,将无状态的HTTP通信协议进一步升级成有状态的通信协议,同时Websocket还支持子协议选项与安全传输.标准的websoc

HTML5:判断浏览器是否支持date类型

在某些情况下,我们需要判断当前浏览器是否支持date类型,如果支持的话,可以让用户用原生的datepicker来选取日期.如果不支持,则我们需要用自己实现的datepicker类库,来提供给用户. 在这里,我们使用Modernizr来实现这一功能,代码如下: 1 if (!Modernizr.inputtypes.date) { 2 $('input[type=date]').datepicker({ 3 }); 4 } HTML5:判断浏览器是否支持date类型,布布扣,bubuko.com

使用 HTML5 WebSocket 构建实时 Web 应用

作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas.本地存储.多媒体编程接口.WebSocket 等等.这其中有"Web 的 TCP "之称的 WebSocket 格外吸引开发人员的注意.WebSocket 的出现使得浏览器提供对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TCP 连接的双向通道.Web 开发人员可以非常方便地使用 WebSocket 构建实时 web 应用,开发人员的手中从此又多了一柄神兵利器.本文首先介绍

初识html5 WebSocket

1.  WebSocket概念 WebSocket是HTML5开始提供的一种Client与Server间进行全双工(full-duplex)通讯的网络技术 双工(duplex),指二台通讯设备之间,允许有双向的资料传输 Client和Server通过WebSocket Protocol建立连接后,双方可以互传数据并且双方都可以关闭此连接 2. HTTP概念 HTTP Protocol是无状态协议的,Client和Server通过HTTP Protocol建立连接后,将采用"request-res

基于构建实时WEb应用的HTML5 WebSocket协议&lt;一&gt;

前言 作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas.本地存储.多媒体编程接口.WebSocket 等等.这其中有"Web 的 TCP "之称的 WebSocket格外吸引开发人员的注意.WebSocket 的出现使得浏览器提供对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TCP 连接的双向通道.WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,Web 开发人员可以非常方便地使用 WebS

基于构建实时WEb应用的HTML5 WebSocket协议&lt;二&gt;

前面说了那么多的理论,我们来看下代码学习. WebSocketAPI简介 首先看一段简单的javascript代码,该代码调用了WebSockets的API. var ws = new WebSocket("ws://echo.websocket.org"); ws.onopen = function(){ws.send("Test!"); }; ws.onmessage = function(evt){console.log(evt.data);ws.close(

让IE支持placeholder属性,跨浏览器placehoder

在html5中,文本框,也就是input, type为text,或者password,新增了一个属性placeholder,也就是占位符,以下是firefox浏览器下的表现形式,当输入的时候,占位符就会消失.这个属性非常好用,因为有这个必要html5才会因素这个属性,然而在IE下,就没有这效果,以下是IE9的表现. 下面是JS版: <!DOCTYPE html> <html> <head> <meta charset="utf-8" />

Html5 WebSocket 技术介绍

WebSocket是html5规范新引入的功能,用于解决浏览器与后台服务器双向通讯的问题,使用WebSocket技术,后台可以随时向前端推送消息,以保证前后台状态统一,在传统的无状态HTTP协议中,这是“无法做到”的. 传统服务端推(server push)技术 WebSocket提出之前,为了解决后台推送消息到前台的需求,提出了一些解决方案,这些方案使用已有的技术(如ajax,iframe,flashplayer,java applet …),通过一些变通的处理来实现. 简单轮询 最简单的是前

[转]使用 HTML5 WebSocket 构建实时 Web 应用

HTML5 WebSocket 简介和实战演练 本文主要介绍了 HTML5 WebSocket 的原理以及它给实时 Web 开发带来的革命性的创新,并通过一个 WebSocket 服务器和客户端的案例来充分展示 WebSocket 的强大和易用. 作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas.本地存储.多媒体编程接口.WebSocket 等等.这其中有“Web 的 TCP ”之称的 WebSocket 格外吸引开发人员的注意.WebSocket 的出现使得浏