1、背景
在开发一些前端页面的时候,总是能接收到这样的需求:如何保持页面并实现自动更新数据呢?以往的常规做法,是前端使用定时轮询后端接口,获取响应后重新渲染前端页面,这种做法虽然能达到类似的效果,但是依然有很多缺点,缺点就不在这里说了,感兴趣的小伙伴可以自行查阅一下。现在让我们回忆一下,我们有没有想过,是否有一种技术,服务器可以主动将数据推送给客户端进行渲染,而不再是客户端向服务器发出请求等待返回结果呢?接下来,让我们一起了解weboskcet。
2、什么是websocket
websocket是HTML5规范的一个部分,它借鉴了socket的思想,实现了浏览器与服务器全双工通信,达到了即时通信的效果。websocket协议基于TCP协议实现,包含初始的握手过程,以及后续的多次数据帧双向传输过程,避免服务器频繁打开多个HTTP连接,从而能更好的节省服务器资源和带宽,提高工作效率与资源利用率

3、工作原理
websocket的通信规范,首先浏览器通过HTTP协议发出websocket的连线请求,服务器进行响应,这个过程称为握手,握手完成后,客户端和服务器之间建立一个类似TCP的连接,使用websocket协议,从而实现它们之间的通信。
4、与HTTP的关系

相同点:
1、都是基于TCP协议,且都是可靠性传输协议;
2、都是应用层协议;
3、websocket支持两种资源标志符ws(默认80端口)与wss(默认443端口),类似HTTP和HTTPS;
不同点:
1、websocket是双向通信协议,HTTP是单向的;
2、websocket是需要浏览器和服务器握手进行建立连接的,HTTP是浏览器发起向服务器的连接,服务器预先并不知道这个连接。
联系点:
websocket在建立握手时,数据是通过HTTP传输的,建立之后的数据传输将不再需要HTTP协议,而是websocket协议;
5、websocket创建与常用的属性方法
5.1 websocket属性
属性 |
描述 |
readyState |
只读属性 readyState 表示连接状态,可以是以下值:0 :表示连接尚未建立。1 :表示连接已建立,可以进行通信。2 :表示连接正在进行关闭。3 :表示连接已经关闭或者连接不能打开。 |
bufferedAmount |
只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。 |
CONNECTING |
值为0,表示正在连接 |
OPEN |
值为1,表示连接已建立,可以进行通信 |
CLOSING |
值为2,表示连接正在关闭 |
CLOSED |
值为3,表示连接已经关闭或者连接不能打开 |
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 | / / 创建websocket
var ws = new WebSocket( "ws://http://www.example.com" );
if (ws.readyState = = ws.CONNECTING){
console.log( '连接正在打开' );
}
ws.onopen = function () {
ws.send(consumerId);
if (ws.readyState = = ws.CONNECTING){
console.log( '连接正在打开1' );
}
if (ws.readyState = = ws. OPEN ){
console.log( '连接已打开' );
}
console.log( '已经建立连接' );
/ / 关闭连接
/ / ws.close()
};
/ / 连接关闭时触发
ws.onclose = function () {
if (ws.readyState = = ws.CLOSED){
console.log( '连接已关闭' )
}
};
/ / 连接错误
ws.onerror = function () {
console.log( '连接错误' );
};
|
5.2 weboscket事件
事件 |
处理程序 |
描述 |
open |
onopen |
连接建立时触发 |
message |
onmessage |
接收消息时触发 |
error |
onerror |
发生错误时触发 |
close |
onclose |
关闭连接时触发 |
5.3 客户端的简单示例
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 | / / 创建websocket
var ws = new WebSocket( "ws://http://www.example.com" );
/ / 连接成功时触发
ws.onopen = function(e) {
console.log( "Connectiong open ..." );
/ / 发送消息
ws.send( "Hello WebSocket" );
};
/ / 接收消息时触发
ws.onmessage = function(e) {
console.log( "Received Message: " + e.data);
ws.close();
};
/ / 关闭连接时触发
ws.onclose = function(e) {
console.log( "Connection closed" );
};
/ / 出现错误时触发
ws.onerror = function(e) {
console.log( "error" );
};
|
5.4 服务端的简单示例
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 | from tornado.websocket import WebSocketHandler
class wsHandler(WebSocketHandler):
connect_users = set ()
def open ( self ):
print ( "开启WebSocket opened" )
self .connect_users.add( self )
def on_close( self ):
self .connect_users.remove( self )
def on_message( self , message):
self .write_message( "接收到客户端的消息:{}" . format (message))
@classmethod
def send_demand_updates( cls , message):
for user in cls .connect_users:
user.write_message(message)
def check_origin( self , origin):
return True
if __name__ = = "__main__" :
wsHandler。send_demand_updates( "服务端发送给客户端的消息" )
|
注意:示例中使用python语言,需依托tornado框架搭建后端web服务端,文章中不再说明如何搭建服务端,感兴趣的小伙伴可自行尝试。tornado内置websocket模块,能更简单的支持使用websocket。
6、总结
websocket提供了一种低延迟、高性能的双向数据通信,不同与web开发的请求、处理、等待响应模式,它是客户端、服务端因为同一个连接直接就可以数据互传的模式,特别适合实时数据交互的应用进行开发。
实用点:
1、websocket连接建立后,后续的数据传输都将以帧序列的形式传输;
2、在客户端断开websocket连接或服务端中断连接前,不需要客户端和服务端重新发起连接请求;
3、在海量并发、客户端与服务器交互负载流量大的情况下,节省网络带宽资源的消耗,且客户端发送与接收消息,都是在同一个持久连接上进行,实现了“真长连接”,真正的实现即时通信。
作者:京东物流 骆铜磊
来源:京东云开发者社区 自猿其说Tech 转载请注明来源