WebSocket草案10文本数据解析实现

握手协议实现了,接下来就是解析数据了,这个相对来说要麻烦很多,相比草案7.6变得更复杂了。下图是数据传输的格式:

各个值的具体含义可以参考这个中文翻译:http://blog.csdn.net/fenglibing/article/details/6852497,英文原文在这里:http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10#section-4.2

简单概括一下就是:FIN一直为1,RSV1、RSV2、RSV3一直为0,当发送内容为文本时,opcode为1,MASK如果为1就使用掩码,需要获取四位掩码,依次轮流和数据做异或运算,第一个内容数据与第一个掩码异或,第二个内容数据与第二个掩码异或……第五个内容数据与第一个掩码异或……一直到结束,然后再对内容进行编码就可以了。

在Chrome/Firefox下面,FIN永远为1,如果只是文本消息,opcode一直是1,RSV1、RSV2、RSV3都为0,所以第一个数据是0x81;MASK为1,再跟上数据长度,所以第二个数据会大于0x80,由于数据长度不一样,其需要占用的字节数也不一样,因此掩码的位置也不一样。根据规范,换算下来是这样:数据总长度(包含FIN、RSV等等信息)小于0x84,则掩码为第三个数据到第六个数据;数据总长度(包含FIN、RSV等等信息)小于0xfe81,则掩码为第五个数据到第八个数据;其他掩码则为第十三个数据到第十六个数据。当数据长度超过一个包的长度时,后面的数据包不再包含RIN、RSV和MASK等信息,二是直接为内容数据,需要根据上一次取到的MASK来做异或运算。…

WebSocket草案10握手协议的实现

Chrome早就采用了websocket草案10的协议,很多以前支持websocket的代码突然之间都用不了了,很多作者也没空更新,索性自己看了下草案,自己实现了一套。

握手协议还是非常简单的,Chrome发过来的header大概是这样的:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 8

要答复的头大概是这样的:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection:

Merpressor —— 在线自动合并、压缩JS文件

最近工作稍微空了点,正好又有幸见到了盛大的在线合并工具,于是一时兴起,把YUI Compressor改造了一下,写了个在线合并JS和CSS的工具,命名为Merpressor,目前已经在工作中使用了。

Mepressor分为两个部分:一部分为公网发布时所用,使用Java编写;另一部分为本地调试时所用,使用轻量和方便的PHP编写。(似乎很绕,简单地讲:Java版本用来公网部署,合并同时压缩代码;PHP版用来本地测试,并不压缩内容。)

在项目中需要合并多个js文件或者css文件时,前端开发者只需修改一个xml格式的配置文件,指定需要合并的文件,通过一定的规则访问,服务器则可自动合并多个js文件,并使用YUI Compressor压缩后返回相应内容,而本地环境下,则会自动导入xml中指定的多个js文件或者css文件,从而使得开发调试和发布一体化,真正做到无缝切换。

注意: 由于合并和压缩需要花费较大的资源和时间,因此在响应速度和并发上会表现较差,在实际使用过程中,需要配合CDN(内容分发网络,一般中大型网站都会采用)使用。当然,你也可以只是把这个工具当合并压缩工具使用。…

不安全的js写法

一种很常见的写法:

document.write('<scr'+'ipt src="http://a.com/b.js" type="text/javascript"></scr'+'ipt>');

直到被杀毒软件提示有恶意代码才发现这也是不安全的,汗……

那就只好改成这样了:

(function() {
    var s = document.createElement('script');
    s.type = 'text/javascript';
    s.src = 'http://a.com.cn/b.js';
    document.getElementsByTagName('head')[0].appendChild(s);
})();

搜了一下,原来还有“邪恶”的eval,具体可以看这里:网马解密大讲堂——网马解密中级篇(Document.write篇)。…

全新极速CSS选择器引擎whiz

好不容易有些空余时间,便拿来写自己的CSS选择器引擎了,这个CSS选择器引擎的目标只有三个:

  • 速度要快
  • 代码要精简
  • 要支持CSS3的选择器。

希望通过这个,能够真正理解那些牛逼的框架中的一部分,比如jQuery,Mootools,YUI等等。花了接近三个星期的时间,大重构了三遍,从最开始的速度极低到现在的极速,每一次都是大换血。在这个过程中,我看到了那些大师写代码的境界,即使我完成了这样一个东西,代码依然很难看。要做一个CSS选择器并没有你想像的那么难,也并不复杂。

大家可能看完性能测试才会有兴趣,下图是一个较全的性能测试结果,大家可以在这里测试,大家可以自己跑一跑看(由于加载的东西较多,请耐心等待一会儿再点start按钮)。

代码量目前还没达到我满意的程度,不过已经足够小了,Gzip之后仅仅只有2KB(YUICompressor压缩之后为8.61K(win NTFS)),另外,针对Firefox 3, Opera…

利用GAE&Google Gears做了一个简单的AJAX代理

做这个的起因很简单:我喜欢用Google Chrome,又喜欢逛豆瓣Google Chrome支持User Scripts了,但是我写的那几个插件在Chrome下又跑不了。因为Google ChromeGoogle Gears,据说可以跨域Ajax,于是弄吧!结果越弄越复杂,因为Google Gears的跨域也是有很多限制的,看来还得服务器跑,还好有Google的App Engine,继续弄下去吧!

当然了,现在这个仅仅只是为Google Gears服务,写的很简单,不过还是比较“Ajax”的,看看简单的示例代码:

<script type="text/javascript" src="gears_init.js"></script>
<script type="text/javascript">
    var options = 

Mootools 1.2教程(23)——滑动效果(Slide)

先废话几句,这第23篇教程一直没有翻译出来,直到今天我看到待审评论里面有这么一条超长的评论,结果一看,居然是这篇教程的翻译稿。这位热心的Mootools爱好者是Fanhp,非常感谢你的辛勤劳动!同时,我感到非常羞愧,实在是有愧大家的期望!愧疚是要拿行动来补的,于是我赶紧对此篇翻译进行了一些整理,修改了其中部分词句,并整理了示例代码。

————————

原文地址:30 Days of Mootools 1.2 Tutorials – Day 23 – Fx.Slide

使用Fx.Slid显示元素

请尊重个人劳动,转载请注明出处:http://fdream.net,译者:Fanhp,整理:Fdream

如果你还没有准备好开始这一讲,请参考这一系列的教程,这里是《MooTools 1.2系列教程目录》

今天继续我们的Mootools…

Mootools常用方法扩展(五)

继续Mootools的扩展,适用于Mootools 1.1及1.2,这次在Element扩展了两个非常简单的方法,一个用来获取或者设置一个元素的innerHTML(这个是模仿jQuery里面的html()方法),还一个方法是把一个表单对象转成hash对象,用得比较少一点。

方法:html

说明:当参数不为空时,设置一个元素的innerHTML,当参数为空时,返回当前元素的innerHTML。

Element.implement({
    html: function(s) {
        ///<summary>
        /// 获取元素的HTML内容或者设置元素的HTML内容
        ///</summary>
        ///<param name="s" type="String">参数为空时,获取HTML内容;参数为字符串时,设置HTML的内容</param>
        ///<returns

Mootools常用方法扩展(四)

继续Mootools常用方法扩展,这次是Window类上的扩展,也就是全局函数。

方法:$params

说明:获取页面URL参数。你可以使用任何指定的分隔符,比如’#’,默认为’#’。

Window.implement({
    $params: function(delimiter) {
        ///<summary>
        /// 获取页面URL的参数,返回包含参数的hash对象
        ///</summary>
        ///<param name="delimiter" type="String">参数和URL的分隔符,比如?或者#,默认为#</param>
        ///<returns type="Hash" />
        delimiter = (delimiter || '#').escapeRegExp();

JavaScript奇怪的比较——隐式类型转换

我们先看一下JavaScript中关系运算符的类型转换规则:

关系运算符(<、>、<=、>=)

  • 试图将 expression1 和 expression2 都转换为数字。
  • 如果两表达式均为字符串,则按字典序进行字符串比较。
  • 如果其中一个表达式为 NaN,返回 false。
  • 负零等于正零。
  • 负无穷小于包括其本身在内的任何数。
  • 正无穷大于包括其本身在内的任何数。

所以很容易理解下面这样的比较:

1 < NaN: false
1 >= NaN: false

'a' < 1: false
'a' >= 1: false

但是下面的就很诡异了:

1 < '2a': false
1 >= '2a': false
'2a' < 1: false
'2a' >= 1: false

按照一般的理解,这里的’2a’应该会被转换成2,可是实际上是被转换成了NaN,why?字符串转换为数字,有parseInt()、parseFloat()和Number(),在这里使用的就是Number转换。在用Number()进行转换时,’2a’是不能被转换成数字的。…