一、WebSocket协议
1、介绍
websocket是一种基于一个TCP连接的全双工的通讯方式,也就是说,服务端可以主动推数据到客户端,客户端也可以发送数据到服务端。
在webcoket中,是由客户端先发送请求头信息到服务端,服务端对请求进行检查,如果是合法的请求头,则会发送握手信息( handshake)到客户端。同是为每个客户端建产一个socket用来通信。这个socket有输入流,也有输出流,是一个全双工的tcp通信端口。
其中客户端的请求头和服务端的握手信息都是每行一个的键值对信息,且字符编码为ASCII 编码。这个很重要,因为在传送数据的时候,是以utf8做编码的。
Websocket 由两部分组成,一部分是浏览器中的WebSocket API(隶属于HTML5规范), 由W3C组织制订;一部分是WebSocket协议(可以用任何语言来实现), 由IETF组织制订。
2、流程
握手:建产握手。这个是整个websocket协议中最重要的一个环节。因为握手是建立连接,或进行下一步通信的关键,也是关系到你是否能和其它遵寻html5 websocket协议的浏览器(如chrome,fiirfox4.0等)进行通信的关键。
当握手成功后,就是进行数据传送了。注意 ,这个时候tcp连接已在经建立了,现在客户发送上来的时候就是纯纯的数据了。服务端要判断什么时候是一次数据请求的开始,什么时候是请求的结束。这个也要是处理在tcp发送中的黏包问题。由于在tcp协议中,会存在两个缓冲区去存放发送的数据或接收的数据,如果没有显的分割符则会让服务端无法正确的识别两条命令。(PS:如果定位数据过多,时间太短会不会造成黏包问题)。
每个端只要向另一端口发送一个0xFF的信息,就表示连接已结束了。这个相关于tcp/ip协议中的fin/ack。
处理websocket链接,服务端只会去识别ws://或wss://开头的请求,这样的话,就不会和其它的监听服务进行冲突出了吧。
注:客户端发送的请求中,服务端地址为wss://www.example.com:8787/im?id=123456
那么www.example.com是服务端的地址,监听的端口号为8787,im是对应的请求名称,其中传送的参数为id,值为123456.
3、API介绍
提供下面三个接口
onopen: 当接口打开时
onmessage: 当收到信息时
onclose: 当接口关闭时
上面的几个方法已在chrome浏览器中得到支持,开发接口也相对简单。
二、WebSocket前端开发
1、浏览器对WebSocket的支持
Google Chrome浏览器最先支持WebSocket,随后是Safari,Firefox,此外最新版本的Opera和IE(Opera11,IE10)也支持WebSocket。下面是主要浏览器的支持情况,Opera11中默认关闭了WebSocket支持,所以这里没有列出,更多信息可参考:http://en.wikipedia.org/wiki/WebSocket 与 http://caniuse.com/#search=websockets
2、客户端WebSocket的主要方法
浏览器支持程度各有区别,前面wiki中关于WebSocket的“Browser support”章节有介绍,遵循w3c关于WebSocket API的相关规范,浏览器提供了WebSocket类型,在Firefox中为MozWebSocket,检测浏览器是否支持WebSocket可以使用下面的脚本代码:
检测浏览器是否支持WebSocket
window.WebSocket = window.WebSocket || window.MozWebSocket; if (!window.WebSocket){ alert("WebSocket not supported by this browser"); return; }
构造函数 - WebSocket#constructor(url, optional protocols)
第一个参数是请求地址,第二个参数选填,表示协议名
使用示例:
var websocket = new WebSocket("ws://127.0.0.1:8080/alarm/alarmServer");
WebSocket事件 #onopen, onmessage, onclose, onerror
连接打开时,回调onopen方法,接收到后台消息时会触发到onmessage事件,后台关闭时调用onclose,出现连接异常时可在onerror中捕获
使用示例:
websocket.onmessage = function(evt){ var data = evt.data; }
方法 - send/close
发送消息 - WebSocket#send(data)
关闭连接 - WebSocket#close(optional code, optional reason)
使用示例:
websocket.send(JSON.stringify({action: "node.remove", id: "001"}));
三、WebSocket后端开发
WebSocket不同于http协议,传统的web服务器通常不支持WebSocket,比如tomcat目前就不支持(tomcat 7.0.26 支持WebSocket了),反倒是一些小众的或者更活跃的web server率先支持WebSocket,如jetty,以及基于node.js的WebSocket-Node扩展,基本上各种编程语言都有相应的服务器可以选择,下图是我列举的几种,详细情况参阅:
http://en.wikipedia.org/wiki/Comparison_of_WebSocket_implementations
1、jetty对WebSocket的实现
http://www.blogjava.net/TWaver/archive/2012/05/03/377244.html
WebSocketServlet基于servlet标准,增加了doWebSocketConnect(...)方法,为客户端请求创建一个后台对应的WebSocket实例。
org.eclipse.jetty.websocket.WebSocketServlet { WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) }
后台WebSocket类,与客户端WebSocket类对应,能监听open, message, close等状态变化事件,并包含一个Connection属性,用于向客户端发送消息。
WebSocket.Connection 后台连接类,包含于WebSocket对象中,用于向客户端推送消息
当然还有其他实现,比如jWebSocket、JBoss 7,以及Tomcat 7,等等
四、WebSocket Java实现
jWebSocket后面详叙。
五、WebSocket Demo
Mozilla开源社区
https://developer.mozilla.org/en-US/demos/search?q=websocket
六、资源链接
http://www.cnblogs.com/dtdnh520/archive/2010/11/09/1873095.html
http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
http://www.cnblogs.com/dtdnh520/archive/2010/11/09/1873103.html
https://developer.mozilla.org/en-US/docs/WebSockets
http://jwebsocket.org/