过去,创建需要在客户端和服务之间双向通信(例如,即时消息和游戏应用)的web应用,需要一个滥用的HTTP来轮询服务器进行更新但以不同的HTTP调用发生上行通知[RFC6202]。
这将导致各种各样的问题:
1、服务器被迫为每个客户端使用一些不同的底层TCP连接: 一个用于发送信息到客户端和一个新的用于每个传入消息。
2、线路层协议有较高的开销,因为每个客户端-服务器消息都有一个HTTP头信息。
3、客户端脚本被迫维护一个传出的连接到传入的连接的映射来跟踪回复。一个简单的办法是使用单个TCP连接双向传输。这是为什么提供WebSocket 协议。与WebSocketAPI结合[WSAPI],它提供了一个HTTP轮询的替代来进行从web 页面到远程服务器的双向通信。WebSocket协议被设计来取代现有的使用HTTP作为传输层的双向通信技术,并
受益于现有的基础设施(代理、过滤、身份验证)。这样的技术被实现来在效率和可靠性之间权衡,因为HTTP最初目的不是用于双向通信(参见[RFC6202]的进一步讨论)。WebSocket协议试图在现有的HTTP基础设施上下文中解决现有的双向HTTP技术目标;同样,它被设计工作在HTTP端口80和443,也支持HTTP代理和中间件,即使这具体到当前环境意味着一些复杂性。但是,这种设计不限制WebSocket到HTTP,且未来的实现可以在一个专用的端口上使用一个更简单的握手,且没有再创造整个协议。最后一点是很重要的,因为交互消息的传输模式不精确地匹配标准HTTP传输并可能在相同组件上包含不常见的负载。
[详见JSR-356WebSocket API规范中文版下载]
Websocket连接的核心不过是HTTP服务器与Client的传统的TCP连接。握手协议主要提供了两者之间的连接的认证。
Client 主动连接:
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
Sec-WebSocket-Key 随机的16个字节的base64编码
Java实现的代码:
private String createSecret() { byte[] nonce = new byte[16]; for (int i = 0; i < 16; i++) { nonce[i] = (byte) (Math.random() * 256); } return Base64.encodeToString(nonce, Base64.DEFAULT).trim(); }
服务端的响应
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat
如果来自服务器响应的Sec-WebSocket-Accept和通过client 发送的Sec-WebSocket-Key +GUID(258EAFA5-E914-47DA-95CA-C5AB0DC85B11) SHA1加密后,在进行base64编码值是相同的,那么表示client和服务器握手成功。
计算Sec-WebSocket-Accept
private String expectedKey(String secret) { //concatenate, SHA1-hash, base64-encode try { final String GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; final String secretGUID = secret + GUID; MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] digest = md.digest(secretGUID.getBytes()); return Base64.encodeToString(digest, Base64.DEFAULT).trim(); } catch (NoSuchAlgorithmException e) { return null; } }
一个WebSocket的模拟的连接:
在握手成功后,便直接通过socket会话的形式进行数据的交互;
在WebSocket协议中,数据使用帧序列来传输。
通过对数据格式的拼装实现数据帧的传输。
[详见JSR-356WebSocket API规范中文版下载] 第六章数据帧的格式。
WebSocket 协议的参考地址:
http://www.cnblogs.com/hustskyking/p/websocket-with-php.html
http://zh.wikipedia.org/zh-cn/WebSocket
JSR-356 WebSocket API规范中文版下载