WebSocket协议
来源:互联网 发布:厦门软件培训机构 编辑:程序博客网 时间:2024/05/16 05:10
1.1 背景
1.2 协议概览
协议包含两部分:握手,数据传输。
客户端的握手如下:
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
服务端的握手如下: HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat
客户端和服务端都发送了握手,并且成功,数据传输即可开始。
1.3 发起握手
发起握手是为了兼容基于HTTP的服务端程序,这样一个端口可以同时处理HTTP客户端和WebSocket客户端
因此WebSocket客户端握手是一个HTTP Upgrade请求: 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
握手中的域的顺序是任意的。
5 数据帧
5.1 概述
WebScoket协议中,数据以帧序列的形式传输。
考虑到数据安全性,客户端向服务器传输的数据帧必须进行掩码处理。服务器若接收到未经过掩码处理的数据帧,则必须主动关闭连接。
服务器向客户端传输的数据帧一定不能进行掩码处理。客户端若接收到经过掩码处理的数据帧,则必须主动关闭连接。
针对上情况,发现错误的一方可向对方发送close帧(状态码是1002,表示协议错误),以关闭连接。
5.2 帧协议
WebSocket数据帧结构如下图所示:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) | |N|V|V|V| |S| | (if payload len==126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | Extended payload length continued, if payload len == 127 | + - - - - - - - - - - - - - - - +-------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+ | Masking-key (continued) | Payload Data | +-------------------------------- - - - - - - - - - - - - - - - + : Payload Data continued ... : + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Payload Data continued ... | +---------------------------------------------------------------+
FIN:1位表示这是消息的最后一帧(结束帧),一个消息由一个或多个数据帧构成。若消息由一帧构成,起始帧即结束帧。
RSV1,RSV2,RSV3:各1位MUST be 0 unless an extension is negotiated that defines meanings for non-zero values. If a nonzero value is received and none of the negotiated extensions defines the meaning of such a nonzero value, the receiving endpoint MUST _Fail the WebSocket Connection_.这里我翻译不好,大致意思是如果未定义扩展,各位是0;如果定义了扩展,即为非0值。如果接收的帧此处非0,扩展中却没有该值的定义,那么关闭连接。
OPCODE:4位解释PayloadData,如果接收到未知的opcode,接收端必须关闭连接。0x0表示附加数据帧0x1表示文本数据帧0x2表示二进制数据帧0x3-7暂时无定义,为以后的非控制帧保留0x8表示连接关闭0x9表示ping0xA表示pong0xB-F暂时无定义,为以后的控制帧保留
MASK:1位用于标识PayloadData是否经过掩码处理。如果是1,Masking-key域的数据即是掩码密钥,用于解码PayloadData。客户端发出的数据帧需要进行掩码处理,所以此位是1。
Payload length:7位,7+16位,7+64位PayloadData的长度(以字节为单位)。如果其值在0-125,则是payload的真实长度。如果值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。注意,网络字节序,需要转换。如果值是127,则后面8个字节形成的64位无符号整型数的值是payload的真实长度。注意,网络字节序,需要转换。长度表示遵循一个原则,用最少的字节表示长度(我理解是尽量减少不必要的传输)。举例说,payload真实长度是124,在0-125之间,必须用前7位表示;不允许长度1是126或127,然后长度2是124,这样违反原则。Payload长度是ExtensionData长度与ApplicationData长度之和。ExtensionData长度可能是0,这种情况下,Payload长度即是ApplicationData长度。
WebSocket协议规定数据通过帧序列传输。
客户端必须对其发送到服务器的所有帧进行掩码处理。
服务器一旦收到无掩码帧,将关闭连接。服务器可能发送一个状态码是1002(表示协议错误)的Close帧。
而服务器发送客户端的数据帧不做掩码处理,一旦客户端发现经过掩码处理的帧,将关闭连接。客户端可能使用状态码1002。
代码实现
https://github.com/OshynSong/web/blob/master/websocket.class.php
js代码:
var url = "ws://xxxx.baidu.com:8088";
var ws = new WebSocket(url);
ws.onopen = function(){
console.log("握手成功,打开socket连接了。。。");
console.log("ws.send(Websocket opened)");
ws.send(("Websocket opened!"));
ws.send('xxxxxxxxxx');
};
ws.onmessage = function(e){
console.log("message:" + e.data);
};
ws.onclose = function(){
console.log("断开socket连接了。。。");
};
ws.onerror = function(e){
console.log("ERROR:" + e.data);
};
- websocket协议
- WebSocket协议
- WebSocket协议
- Websocket协议
- Websocket协议
- webSocket协议
- WebSocket协议
- WebSocket协议
- Websocket协议
- websocket协议
- WebSocket协议
- WebSocket 协议
- webSocket协议
- WebSocket协议
- WebSocket 协议
- Http 协议,WebSocket 协议
- WebScoket 规范 + WebSocket 协议
- websocket协议10版本
- LEETCODE 172
- 用C++面向对象的方式动态加载so
- ubuntu下添加第三方软件包 add-apt-repository
- MMX与SSE优化策略描述
- Java NIO使用及原理分析(二)
- WebSocket协议
- [并查集] poj2236 Wireless Network
- my97Datepicker 日期工具
- 咱们来看看谷歌Design包里的SnackBar
- Context的startActivity方法
- Eclipse工具插件开发之Table表格上控件刷新的问题
- 简单配置搞定 Nginx + Tomcat + HTTPS
- 怎样使一个输入框隐藏显示,仅仅需要该输入框保存值(比如保存id)
- iOS使用NSUserDefaults 存储数据报Attempt to set a non-property-list object as an NSUserDefaults value的错误解决