WebSocket 是一种网络通讯协议。RFC6455定义了它的通讯标准。javascript
WebSocket 是 HTML5 开始提供的一种在单个 TCP 链接上进行全双工通信的协议。html
咱们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据;这种客户端是主动方,服务端是被动方的传统Web模式 对于信息变化不频繁的Web应用来讲形成的麻烦较小,而对于涉及实时信息的Web应用却带来了很大的不便。vue
所以,随着HTML5的诞生,一种新的通讯协议应运而生---WebSocket,他最大的特色就是服务端能够主动向客户端推送消息,客户端也能够主动向服务端发送消息,实现了真正的平等。java
举个例子:如带有即时通讯、实时数据、订阅推送等功能的应用。在WebSocket规范提出以前,开发人员若要实现这些实时性较强的功能,常常会使用折衷的解决方法:ajax轮询(最原始的实现实时Web应用的解决方案)web
ajax轮询的原理:ajax轮询的原理很是简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。明显地,这种方法会致使过多没必要要的请求,浪费流量和服务器资源。
场景再现:
客户端:有没有新信息(Request)
服务端:没有(Response)
客户端:有没有新信息(Request)
服务端:没有。。(Response)
客户端:有没有新信息(Request)
服务端:你好烦啊,没有啊。。(Response)
客户端:有没有新消息(Request)
服务端:有啦,给你。(Response)
客户端:有没有新消息(Request)
服务端:。。。。。没。。。。没。。。没有(Response) ---- loopajaxwebsocket的原理:当服务器完成协议升级后(HTTP->Websocket),服务端就能够主动推送信息给客户端啦。
场景再现:
客户端:我要创建Websocket协议,须要的服务:chat,Websocket协议版本:17(HTTP Request)
服务端:确认,已升级为Websocket协议(HTTP Protocols Switched)
客户端:麻烦你有信息的时候推送给我噢。。
服务端:好的,有的时候会告诉你的。
服务端:balabalabalabala
服务端:哈哈哈哈哈啊哈哈哈哈
服务端:笑死我了哈哈哈哈哈哈哈浏览器
(1)创建在 TCP 协议之上,服务器端的实现比较容易。服务器
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,而且握手阶段采用 HTTP 协议,所以握手时不容易屏蔽,能经过各类 HTTP 代理服务器。websocket
(3)数据格式比较轻量,性能开销小,通讯高效。网络
(4)能够发送文本,也能够发送二进制数据。
(5)没有同源限制,客户端能够与任意服务器通讯。
(6)协议标识符是ws
(若是加密,则为wss
),服务器网址就是 URL。
浏览器经过 JavaScript 向服务器发出创建 WebSocket 链接的请求,链接创建之后,客户端和服务器端就能够经过 TCP 链接直接交换数据。当你获取 WebSocket 链接后,你能够经过 send() 方法来向服务器发送数据,并经过 onmessage 事件来接收服务器返回的数据。
// url, 指定链接的 URL
// protocol 是可选的,指定可接受的子协议。
let Socket = new WebSocket(url, [protocol] );
复制代码
假设咱们建立了一个Socket对象
属性 | 描述 |
---|---|
Socket.readyState | 只读属性 readyState 表示链接状态,能够是如下值: 0 - 表示链接还没有创建。 1 - 表示链接已创建,能够进行通讯。 2 - 表示链接正在进行关闭。 3 - 表示链接已经关闭或者链接不能打开。 |
Socket.bufferedAmount | 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,可是尚未发出的 UTF-8 文本字节数。 |
假设咱们建立了一个Socket对象
事件 | 事件处理程序 | 描述 |
---|---|---|
open | Socket.onopen | 链接创建时触发 |
message | Socket.onmessage | 客户端接收服务端数据时触发 |
error | Socket.onerror | 通讯发生错误时触发 |
close | Socket.onclose | 链接关闭时触发 |
假设咱们建立了一个Socket对象
方法 | 描述 |
---|---|
Socket.send() | 使用链接发送数据 |
Socket.close() | 关闭链接 |
【1】原生JavaScript实现WebSocket链接
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <style> </style> <body> <input id="text" type="text" /> <button onclick="send()">发送消息</button> <button onclick="closeWebSocket()">关闭WebSocket链接</button> <div id="message"></div> <script> let websocket = null; //判断当前浏览器是否支持WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8080/websocket"); } else { alert('当前浏览器不支持websocket!') } //链接发生错误的回调方法 websocket.onerror = function () { console.log("WebSocket链接发生错误"); }; //链接成功创建的回调方法 websocket.onopen = function () { console.log("WebSocket链接成功"); } //接收到消息的回调方法 websocket.onmessage = function (event) { document.getElementById('message').innerHTML += event.data + '<br/>'; } //链接关闭的回调方法 websocket.onclose = function () { console.log("WebSocket链接关闭"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket链接,防止链接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function () { closeWebSocket(); } //关闭WebSocket链接 function closeWebSocket() { websocket.close(); } //发送消息 function send() { let message = document.getElementById('text').value; websocket.send(message); } </script> </body> </html>复制代码
【2】在vue项目中实现WebSocket链接
<template> <div> <el-input v-model="params" clearable/> <el-button type="primary" @click="send">发消息</el-button> </div> </template> <script> export default { data() { return { params: '', path: "ws://localhost:8080/websocket", socket: "" } }, mounted() { // 初始化 this.init() }, destroyed() { // 销毁监听 this.socket.onclose = this.close }, methods: { init: function () { if (typeof (WebSocket) === "undefined") { console.log("您的浏览器不支持socket") } else { // 实例化socket this.socket = new WebSocket(this.path) // 监听socket链接成功回调 this.socket.onopen = this.open // 监听socket链接失败回调 this.socket.onerror = this.error // 监听后台返回的socket消息 this.socket.onmessage = this.getMessage } }, open: function () { console.log("socket链接成功") }, error: function () { console.log("链接错误") }, getMessage: function (msg) { console.log(msg.data) }, send: function () { this.socket.send(params) }, close: function () { console.log("socket已经关闭") } } } </script>复制代码