WebSocket
WebSocket是一种基于TCP连接的全双工通信的协议,其工作在应用层,建立连接的时候通过复用http握手通道,完成http协议的切换升级,即切换到WebSocket协议,协议切换成功后,将不再需要客户端发起请求,服务端就可以直接向客户端发送数据,实现双向通信。 相对于Http协议而言,WebSocket有以下优点:
- 可以支持双向通信
- WebSocket协议可以更好的支持二进制,可以直接传送二进制数据。
- 同时WebSocket协议的头部非常小,服务器发到客户端的数据包的包头,只有2~10个字节(取决于数据包的长度),客户端发送服务端的包头稍微大一点,因为其要进行掩码加密,所以还要加上4个字节的掩码。总得来说,头部不超过14个字节。
- 支持扩展,用户可以扩展协议实现自己的子协议。
WebSocket 建立连接
握手过程
- 浏览器、服务器建立TCP连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行。
- TCP连接成功后,浏览器通过HTTP协议向服务器传送WebSocket支持的版本号等信息。(开始前的HTTP握手)
- 服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据。http header特殊数据
- Connection: Upgrade 表示要升级协议
- Upgrade: websocket 表示要升级到websocket协议
- Sec-WebSocket-version 表示websocket的版本。
- Sec-WebSocket-Key 浏览器生成的一个字符串,服务器端需要取出该字符串,后通过SHA1算法计算出摘要,并转成base64字符串,然后作为
Sec-WebSocket-Accept的值放到响应头部返回给客户端,否则会连接失败。关键就是要监听upgrade事件,然后根据Sec-WebSocket-Key生成对应Sec-WebSocket-Accept的key值,然后返回给客户端
- 当收到了连接成功的消息后,通过TCP通道进行传输通信。
深入探究
WebSocket 复用了 HTTP 的握手通道。具体指的是,客户端通过 HTTP 请求与 WebSocket 服务端协商升级协议。
协议升级完成后,后续的数据交换则遵照 WebSocket 的协议。
建立链接时需要密钥验证,公开算法,可破解伪造,只是为了避免误操作。
数据帧交互: opcode有Ping,Pong, 二进制交换,断开连接等。
有分片逻辑,最后一帧的FIN为1
客户端到服务端请求需要进行掩码转换,数据不同意伪造。
客户端流程
// 初始化一个 WebSocket 对象
var ws = new WebSocket("ws://localhost:9998/echo");
// 建立 web socket 连接成功触发事件
ws.onopen = function () {
// 使用 send() 方法发送数据
ws.send("发送数据");
alert("数据发送中...");
};
// 接收服务端数据时触发事件
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("数据已接收...");
};
// 断开 web socket 连接成功触发事件
ws.onclose = function () {
alert("连接已关闭...");
};
HTTP 长连接
HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。
这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步JavaScript和XML(AJAX)请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
一些“服务器推”技术。
轮询 客户端以一定的时间间隔发送Ajax请求,优点实现起来比较简单、省事,不过缺点也很明显,请求有很大一部分是无用的,而且需要频繁建立和释放TCP连接,很消耗带宽和服务器资源。
长轮询 与普通轮询不同的地方在于,服务端接收到请求后会保持住不立即返回响应,等到有消息更新才返回响应并关闭连接,客户端处理完响应再重新发起请求。较之普通轮询没有无用的请求,但服务器保持连接也是有消耗的,如果服务端数据变化频繁的话和普通轮询并无两样。
长连接 在页面中嵌入一个隐藏的iframe,将其src设为一个长连接的请求,这样服务端就能不断向客户端发送数据。优缺点与长轮询相仿。
这些技术都明显存在两个相同的缺点:
- 服务器需要很大的开销
- 都做不到真正意义上的“主动推送”,服务端只能“被动”地响应,于是就轮到正主出场了。在websocket中,只需要做一个握手动作就可以在客户端和服务器之间建立连接,之后通过数据帧的形式在这个连接上进行通讯,并且,由于连接是双向的,在连接建立之后服务端随时可以主动向客户端发送消息(前提是连接没有断开)。
VS http
相同点
- 都是一样基于TCP的,都是可靠性传输协议。
- 都是应用层协议。
不同点
- WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
- WebSocket是需要握手进行建立连接的。
联系:WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
VS Socket
Socket是传输控制层协议,WebSocket是应用层协议。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。