websocket 简介
websocket 是什么
1,websocket 是一种网络通信协议。RFC6455 定义了它的通信标准。
2,websocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通信的协议。
websocket 协议的特点
1,其最大的特点就是服务器可以主动的向客户端推送消息,客户端也可以主动向服务器发送消息,是真正的双向平等对话,属于服务器推送技术的一种。
2,它建立在 TCP 协议之上,服务端的实现比较容易。
3,与 HTTP 协议有着良好的兼容性。默认端口也是 80 和 443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
4,可以发送文本,也可以发送二进制数据。
5,没有同源限制,客户端可以与任意服务器通信。
6,协议标识符是 ws(如果加密则为 wss),服务器网址就是 URL。
- 如:ws://example.com:80/some/path
http 协议
1,http 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能有客户端发起,服务端对请求做出应答处理。
对比双工通信协议 http 协议的弊端
1,http 协议无法实现服务器主动向客户端发起消息。
2,这种单向请求的特点注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦,大多数 web 应用程序将通过频繁的异步 ajax 请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
3,http 协议与 websocket 协议对比:
4,websocket 协议分为两部分,分别为:握手(基于 http 协议)和数据传输。
- 来自客户端的握手看起来像如下形式:
1 | GET ws://localhost/chat HTTP/1.1 |
- 来自服务器的握手看起来像如下形式:
1 | HTTP/1.1 101 Switching Protocols |
- 字段说明:
Connection: Upgrade:标识该 HTTP 请求是一个协议升级请求。
Upgrade: websocket:协议升级为 websocket 协议。
Sec-webSocket-Version: 13:客户端支持 websocket 的版本。
Sec-webSocket-Key:客户端采用 base64 编码的 24 位随机字符序列,服务器接受客户端 HTTP 协议升级的证明。要求服务端响应一个对应加密的 Sec-webSocket-Accept 头信息作为应答。
Sec-webSocket-Extensions:标识协议扩展类型。
websocket 对象
1,实现 websocket 的 web 浏览器将通过 websocket 对象公开所有必需的客户端功能(主要指支持 Html5 的浏览器)。
2,以下 API 用于创建 websocket 对象:
1 | const ws = new websocket(url); |
参数 url 格式说明:ws://ip 地址:端口号/资源名称
websocket 属性
1,webSocket.readyState:属性返回实例对象的当前状态,共有四种。
CONNECTING:值为 0,表示正在连接。
OPEN:值为 1,表示连接成功,可以通信了。
CLOSING:值为 2,表示连接正在关闭。
CLOSED:值为 3,表示连接已关闭,或者打开连接失败。
相关示例如下:
1 | switch (ws.readyState) { |
2,webSocket.bufferedAmount:实例对象的 bufferedAmount 属性,表示还有多少字节的二进制数据没有发送出去。它可以用来判断发送是否结束。
1 | var data = new ArrayBuffer(10000000); |
websocket 事件
1,open:在连接建立时触发。
- 对应事件处理程序:ws.onopen。
1 | ws.onopen = function () { |
如果要指定多个回调函数,可以使用 addEventListener 方法。
1 | ws.addEventListener("open", function (event) { |
2,message:客户端接收服务端数据时触发。
- 对应事件处理程序:ws.onmessage。
1 | ws.onmessage = function (event) { |
- 注意:服务端数据可能是文本,也可能是二进制数据(blob 对象或 Arraybuffer 对象)。
1 | ws.onmessage = function (event) { |
- 除了动态判断收到的数据类型,也可以使用 binaryType 属性,显示指定收到的二进制数据类型。
1 | // 收到的是 blob 数据 |
3,error:通行发生错误时触发。
- 对应事件处理程序:ws.onerror。
1 | socket.onerror = function (event) { |
4,close:连接关闭时触发。
- 对应事件处理程序:ws.onclose。
1 | ws.onclose = function (event) { |
websocket 方法
1,send():该方法用于在与服务器连接成功时向服务器发送数据。
- 发送文本的示例如下:
1 | ws.send("message"); |
- 发送 Blob 对象的示例如下:
1 | const file = document.querySelector('input[type = "file"]').files[0]; |
- 发送 ArrayBuffer 对象的示例如下:
1 | // Sending canvas ImageData as ArrayBuffer |
服务端相关
1,Tomcat 的 7.0.5 版本开始支持 websocket,并且实现了 Java WebSocket 规范(JSR356)。
2,Java WebSocket 应用由一系列的 WebSocketEndpoint 组成。Endpoint 是一个 Java 对象,代表 websocket 链接的一端,对于服务器,我们可以视为处理具体 WebSocket 消息的接口,就像 Servlet 与 http 请求一样。
3,我们可以通过两种方式定义 Endpoint:
第一种是编程式,即继承类 javax.websocket.Endpoint 并实现其方法。
第二种是注解式,即定义一个 POJO,并添加 @ServerEndpoint 相关注解。
4,Endpoint 实例在 WebSocket 握手时创建,并在客户端与服务端连接过程中有效,最后在连接关闭时结束。在 Endpoint 接口中明确定义了与其声明周期相关的方法,规范实现者确保声明周期的各个阶段调用实例的相关方法,声明周期方法如下:
onClose:当会话关闭时调用。对应注解为:@OnClose。
onOpen:当开启一个新的会话时调用,该方法是
客户端与服务端握手成功后调用
的方法。对应注解为:@OnOpen。onError:当连接过程中异常时调用。对应注解为:@OnError。
5,服务端如何接收客户端发送的数据?
- 通过为 Session 添加 MessageHandler 消息处理器来接收消息。而当采用注解方式定义 Endpoint 时,我们可以通过 @OnMessage 注解指定接收消息的方法。
6,服务端如何推送数据给客户端?
- 发送消息则由 RemoteEndpoint 完成,其实例由 Session 维护,根据数据使用情况,我们可以通过 Session.getBasicRemote 获取同步消息发送的实例,然后调用其 sendXxx() 方法就可以发送消息,可以通过 Session.getAsyncRemote 获取异步消息发送实例。
7,服务端相关代码:
1 |
|
前端建立 websocket 相关代码
1,心跳检测相关思路与说明:
每隔一段指定的时间(计时器),向服务器发送一个数据,服务器收到数据后再发送给客户端,正常情况下客户端通过 onmessage 事件是能监听到服务器返回的数据的,说明请求正常。
如果再这个指定时间内,客户端没有收到服务器端返回的响应消息,就判定连接断开了,使用 websocket.close 关闭连接。
这个关闭连接的动作可以通过 onclose 事件监听到,因此在 onclose 事件内,我们可以调用 websocketReconnect 事件进行重连操作。
1 | export let ws; |
发布时间: 2021-04-01
最后更新: 2022-02-12
本文标题: WebSocket
本文链接: https://dnhyxc.gitee.io/2021/04/01/websocket/
版权声明: 本作品采用 CC BY-NC-SA 4.0 许可协议进行许可。转载请注明出处!