WebSocket
的概念伴随着html5
的出现,其实已经出来很多年了,但是浏览器的支持实现,服务端的支持实现各不相同,Java范畴内也是最近才统一了API实现标准,我匆匆看了一下Oracle提供的实现api,还是比较简洁的,这个jsr356 规范一定要看看。
说到WebSocket
协议,必须先说说http
协议,我们都知道,http
协议最显著的特征就是其通信方式为经典的请求/应答
模式,这种模式存在这么几个问题:
WebSocket
的出现就是为了解决这些问题,它和http
协议的关系很暧昧,本质上来说,WebSocket是不限于HTTP协议的,但是由于现存大量的HTTP基础设施,代理,过滤,身份认证等等,WebSocket借用HTTP和HTTPS的端口。由于使用HTTP的端口,因此TCP连接建立后的握手消息是基于HTTP的,由服务器判断这是一个HTTP协议,还是WebSocket协议。WebSocket连接除了建立和关闭时的握手,数据传输和HTTP没丁点关系了。
在阅读完上文提到的jsr356规范
以后,我这里做了一个web聊天室
的demo,看下代码吧,非常简洁。
首先是服务端,涉及到了这么几个逻辑:
- websocket服务的定义
- 各种事件的监听
- 消息编码/消息解码
websocket服务的定义
1 2 3 4 5
| @ServerEndpoint(value = "/chat/{username}", encoders = MsgEncoder.class, decoders = MsgDecoder.class) public class ChatServer { ...... }
|
服务端各种事件的监听
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| @OnOpen public void open(Session session, @PathParam("username") String username) { SESSIONS.add(session); DBObject data = new BasicDBObject("username", username); Msg msg = new Msg(Msg.type_0_online, data); sendMsg(msg); }
@OnClose public void close(Session session, @PathParam("username") String username) { SESSIONS.remove(session); DBObject data = new BasicDBObject("username", username); Msg msg = new Msg(Msg.type_1_offline, data); sendMsg(msg); }
@OnMessage public void message(Session session, Msg msg, @PathParam("username") String username) { sendMsg(msg); }
private void sendMsg(Msg msg) { for (Session session : SESSIONS) { try { session.getBasicRemote().sendObject(msg); } catch (IOException e) { e.printStackTrace(); } catch (EncodeException e) { e.printStackTrace(); } } }
|
再来看看客户端的逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function startWebSocket(url, onopen, onmessage, onclose) { var ws = null; if ('WebSocket' in window) { ws = new WebSocket(url); } else if ('MozWebSocket' in window) { ws = new MozWebSocket(url); } else { alert('Websocket is not supportted ') } ws.onopen = onopen; ws.onclose = onclose; ws.onmessage = onmessage; window.ws = ws; }
|
最核心的逻辑都在这个方法里面了,是不是非常简单,下面看看效果图吧。
最后,附上源码地址。