Websockets everywhere with Socket.IO - ifree's Blog - it's my way
使用HTML5的Canvas和raycasting创建一个伪3D游戏(part1)

Websockets everywhere with Socket.IO

ifree posted @ Nov 02, 2010 10:38:09 AM in 翻译 with tags flash socket soket websocket Comet html5 , 3344 readers

最近一个小伙子过来吐槽,说ajax弱了,实现不了长链接,然后就一直哭....其实这未必不能实现,至于长链接,comet,server push都是依托与服务器的,如果服务器实现了server push那就好说了,据我了解现在的服务器大多都支持apache,jetty,fast cgi,ninix(重新加NGiNX_HTTP_Push_Module编译),但是这往往不够...好了,这样说不给力,下面我翻译了一篇Socket.IO.Js的文章里面较详细介绍了关于使用ajax保持http长连接的实现,以及Socket.IO的实现(就是兼容版实现Websockets ),同时涉及了Node.js(自己google)

http://howtonode.org/websockets-socketio

----转载请注明作者信息 ifree

 

正文:

如果你一直致力于实时网络应用,在过去几年你可能了解过一些不同的改善server端和client端数据交互延迟的技术.如果你正在开发一款多人游戏,一个及时聊天系统 或者一个想twitter一样需要频繁的与服务短交互的应用,你可能想'反转'传统的交互模型.所以,与其向服务端发送请求不如让服务端发送数据给你.

如今,当我们开发类似实时的系统是,我们总会想到长连接,comet当然还有websocket.但是,他们各有各的局限性,比如,服务器实现不同,限制太多,浏览器支持不够...

下面是我的Socket.IO的一段代码:

var socket = new io.Socket();
socket.on('connect', function(){
    // connected!
});
socket.on('message', function(msg){
    // message coming
});
socket.send('Hello world!');

如果你比较熟悉WebSocket(不熟悉去看api),其主要目的是简化HTTP的双向协议.你会发现它们非常类似.但是不同的是(由于目前浏览器尚未完全实现html5) Socket.IO支持 IE6-9, Firefox 3-4, Safari 3-5, Chrome 3-6, iOS (iPhone ,iPad)和其他兼容浏览器.

 

回顾当前的实时网络实现

在这个年代,一大部分web开发人员都在使用AJAX来实现实时交互(异步交互),就像Socket.IO一样.一些第三方js库比如jQuery,封装了兼容性较好的ajax对象来达到异步请求的功能.

比如说,如果你现在打算实时地向服务器请求资源,你可能会这样做:

 

setInterval(function(){
    $.ajax({ url: '/my/page', success: function(data){
        // do something with the data
    } });
}, 5000);

这样,每五秒钟从服务器获取数据.在我看来,这几乎是和rfc1149(ip数据报)的规范一样高效.

你可能也会减少等待的时间:

 

setInterval(function(){
    $.ajax({ url: '/my/page', success: function(data){
        // do something with the data
    } });
}, 100);

然而,你可能忽略了下面两个要点:

  • HTTP延迟.一个数据包在高速网络中往返可能消耗200ms,但是情况不总是这样,如果是500或更高,而且有时还不必要.因为:
  • 服务器可能没有我们要的数据,这样一来导致了很多不必要的带宽浪费.

 

长轮询

传统轮询的方法是不间断的向服务器请求数据,要克服它的缺点就要在服务器没有数据时保持长连接.这样也戏剧性的减少了网络延迟(长连接),所以,这也算一种服务器推送的技术.

 

function load(){
    $.ajax({ url: '/my/page', success: function(){
        // do something with the data
    }, complete: load, timeout: 20000 });
}

 

 

如何做到长连接

如果你来自一个更传统的软件开发行业(比如桌面软件),你可能会想,我们为什么不保持长连接呢.

在浏览器上要实现可能有两种方法:

  • XMLHttpRequest 和 multipart/x-mixed-replace MIME 类型 (即在xhr请求中设置multipart为true的XMLHTTP实例);

虽然早在1995年Netsacpe就推出了这项技术(但不是对所有浏览器都有效),唯一在firefox浏览器下被普遍支持.

  • 使用 <iframe>时在头部meta信息设置 Transfer-encoding: chunked and Connection: keep-alive.

这样可以在创建<script>标签,动态执行脚本,iframe内部刷新而保持父窗口不刷新,这样也可以被看作是一种服务器推送的方法.

但这样做有一个缺点,就是浏览器下方出现无休止的进度条,严重的损害了用户体验.在ie环境下,可以把 <iframe> 放到一个隐藏的文档对象中(用ActiveX对象创建的htmlfile对象).在gmail 里面的gtalk实现给就是用的这个技术.是由Alex Russell 分析/发现的.

现在,很明显地看到这些技术在一定的环境下发挥了作用.但是最根本的是现在的服务器有着不同的请求的方法:

  • 请求头部信息(Content-Type, Connection...).
  • 持续连接(这需要长轮询的支持,但不是完全支持).
  • 框架信息.对于multipart,每条消息都要由'-----'分割符隔开解析麻烦(是的,每个请求的数据都被'----------'分割,请看请求数据).
  • 浏览器怪癖(比如ie在请求时需要一些空字节来识别每一条数据).

所有这些所做的都是尽可能减少数据的延迟,但是通常我们只把XMLHTTPRequest作为一个想服务端传输数据的良好解决方案.

 

通用的解决方案

有了WebSocket,"一个致力于解决bs架构的双端交互并且不依靠'multiple HTTP连接' ",像它的作者Hickson说的那样.

WebSocket 利用了HTTP/1.1规范的优势,可以说这是一个全新的协议:(有兴趣看rfc)

 

The Upgrade general-header allows the client to specify what additional communication protocols it supports and would like to use if the server finds it appropriate to switch protocols.
Examples: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

 

 

WebSocket在收发消息的时候并不关闭连接.除了本身的安全模型(基于utf-8编码的框架)以外,它可以完全被称作"web版的TCP".

但是WebSocket仍存在一些问题:

  • 服务器必须单独处理WebSocket请求,执行WebSocket特有的握手协议,WebSocket的协议.
  • 没有广泛的浏览器支持.

 

使用Node.js

Node.js 给开发人员带来了一个独特且令人兴奋的特性:你可以用当下最流行的脚本技术来编写你的无阻塞web服务器.

就像这样:

http.createServer(function (request, response) {
    setTimeout(function(){
        response.writeHead(200, {'Content-Type': 'text/plain'});
      response.end('Hello World\n');
    }, 20000);
}).listen(8124);

 

虽然有了这个简单的api,但是你很难继续加强你的程序的逻辑.但是Socket.IO-node可以提供一个辅助的实现.下面是一个聊天程序差不多10行,同时支持服务器广播:

 

var buffer = [];
io.on('connection', function(client){
    client.send({ buffer: buffer });
    client.broadcast({ announcement: client.sessionId + ' connected' });

    client.on('message', function(message){
        var msg = { message: [client.sessionId, message] };
        buffer.push(msg);
        if (buffer.length > 15) buffer.shift();
        client.broadcast(msg);
    });

    client.on('disconnect', function(){
        client.broadcast({ announcement: client.sessionId + ' disconnected' });
    });
});

最好的是,在浏览里,它会处理你的长连接,flash socket,iframe请求.很棒把.

 

进一步阅读

如果你想进一步研究Socket.IO,你可以在git repositories检出源码进一步研究,也可以看一下几个项目(注:node.js是基于v8js引擎实现的高性能web服务器,很爽有时间去看吧):

googlebot said:
Dec 07, 2010 08:37:52 PM

goo.gl/COqXE
your short url

Rylan Landon said:
Dec 29, 2018 06:22:51 PM

The web is actually bogged lower along with phony weblogs without any actual information however the publish had been wonderful as well as really worth the actual study. Thanks with regard to discussing this particular beside me. Crawley Accountants


Login *


loading captcha image...
(type the code from the image)
or Ctrl+Enter