在项目中用到socket.io在WEB端做消息推送,遂花了点时间看了socket.io实现,做个简单分析,如有错漏,欢迎指正。
1概述socket.io是一个基于WebSocket的CS的实时通信库,它底层基于engine.io。engine.io使用WebSocket和xhr-polling(或jsonp)封装了一套自己的协议,在不支持WebSocket的低版本浏览器中(支持websocket的浏览器版本见这里)使用了长轮询(longpolling)来代替。socket.io在engine.io的基础上增加了namespace,room,自动重连等特性。
本文接下来会先简单介绍websocket协议,然后在此基础上讲解下engine.io和socket.io协议以及源码分析,后续再通过例子说明socket.io的工作流程。
2WebSocket协议我们知道,在HTTP协议开发的时候,并不是为了双向通信程序准备的,起初的web应用程序只需要“请求-响应”就够了。由于历史原因,在创建拥有双向通信机制的web应用程序时,就只能利用HTTP轮询的方式,由此产生了“短轮询”和“长轮询”(注意区分短连接和长连接)。
短轮询通过客户端定期轮询来询问服务端是否有新的信息产生,缺点也是显而易见,轮询间隔大了则信息不够实时,轮询间隔过小又会消耗过多的流量,增加服务器的负担。长轮询是对短轮询的优化,需要服务端做相应的修改来支持。客户端向服务端发送请求时,如果此时服务端没有新的信息产生,并不立刻返回,而是Hang住一段时间等有新的信息或者超时再返回,客户端收到服务器的应答后继续轮询。可以看到长轮询比短轮询可以减少大量无用的请求,并且客户端接收取新消息也会实时不少。
虽然长轮询比短轮询优化了不少,但是每次请求还是都要带上HTTP请求头部,而且在长轮询的连接结束之后,服务器端积累的新消息要等到下次客户端连接时才能传递。更好的方式是只用一个TCP连接来实现客户端和服务端的双向通信,WebSocket协议正是为此而生。WebSocket是基于TCP的一个独立的协议,它与HTTP协议的唯一关系就是它的握手请求可以作为一个Upgraderequest经由HTTP服务器解析,且与HTTP使用一样的端口。WebSocket默认对普通请求使用80端口,协议为ws://,对TLS加密请求使用端口,协议为wss://。
握手是通过一个HTTPUpgraderequest开始的,一个请求和响应头部示例如下(去掉了无关的头部)。WebSocket握手请求头部与HTTP请求头部是兼容的(见RFC)。
##RequestHeaders##Connection:UpgradeHost:socket.io.demo.