前言
WebSocket是一种网络通信协议,很多高级功能都需要用到它。
有些人会想,既然我们已经有了HTTP协议了,为什么还要花时间学另一种协议呢?这个协议到底有什么魔力,值得我们花时间学它。
因为 HTTP 协议有一个缺陷:通信只能由客户端发起。只能是客户端向服务器发出请求,服务器返回查询结果。做不到服务器主动向客户端推送信息。如果碰到一些需要服务端频繁给客户端推送信息的需求,我们用HTTP协议来实现就很麻烦。隔一段时间客户端就发起询问,了解服务器有没有新的信息。这种需求典型的例子就是聊天室,需要不断更新聊天室的内容。
轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。
简介
WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。WebSocket 允许服务器端与客户端进行全双工(full-duplex)的通信。举例来说,HTTP 协议有点像发电子邮件,发出后必须等待对方回信;WebSocket 则是像打电话,服务器端和客户端可以同时向对方发送数据,它们之间存着一条持续打开的数据通道。
WebSocket还有其他特点,如下:
- 建立在 TCP 协议之上,服务器端的实现比较容易。
- 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
- 可以发送文本,也可以发送二进制数据。
- 没有同源限制,客户端可以与任意服务器通信,完全可以取代 Ajax。
- 数据格式比较轻量,性能开销小,通信高效。
- 协议标识符是
ws
(如果加密,则为wss
,对应 HTTPS 协议),服务器网址就是 URL。
WebSocket握手
浏览器发出的 WebSocket 握手请求类似于下面的样子:
GET / HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Host: example.com
Origin: null
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
上面的头信息之中,有一个 HTTP 头是Upgrade
。HTTP1.1 协议规定,Upgrade
字段表示将通信协议从HTTP/1.1
转向该字段指定的协议。Connection
字段表示浏览器通知服务器,如果可以的话,就升级到 WebSocket 协议。Origin
字段用于提供请求发出的域名,供服务器验证是否许可的范围内(服务器也可以不验证)。Sec-WebSocket-Key
则是用于握手协议的密钥,是 Base64 编码的16字节随机字符串。
服务器的 WebSocket 回应如下。
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Origin: null
Sec-WebSocket-Location: ws://example.com/
上面代码中,服务器同样用Connection
字段通知浏览器,需要改变协议。Sec-WebSocket-Accept
字段是服务器在浏览器提供的Sec-WebSocket-Key
字符串后面,添加 RFC6456 标准规定的“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”字符串,然后再取 SHA-1 的哈希值。浏览器将对这个值进行验证,以证明确实是目标服务器回应了 WebSocket 请求。Sec-WebSocket-Location
字段表示进行通信的 WebSocket 网址。
完成握手以后,WebSocket 协议就在 TCP 协议之上,开始传送数据。
客户端使用WebSocket的简单示例
WebSocket的使用方式很简单,如下就是客户端的简单使用示例:
const socket = new WebSocket("ws://localhost:8080");
socket.addEventListener('open',(evt)=>{
console.log('Connection open ...');
socket.send('Hello WebSockets!');
})
// socket.onopen = function(evt) {
// console.log('Connection open ...');
// socket.send('Hello WebSockets!');
// };
socket.addEventListener('message',(evt)=>{
console.log('Received Message: ' + evt.data);
socket.close();
})
// socket.onmessage = function(evt) {
// console.log('Received Message: ' + evt.data);
// socket.close();
// };
socket.addEventListener('close',(evt)=>{
console.log('Connection closed.');
})
// socket.onclose = function(evt) {
// console.log('Connection closed.');
// };
socket.addEventListener('error',(evt)=>{
console.log("WebSocket error: ", event);
})
// socket.onerror = function(evt) {
// console.log("WebSocket error: ", event);
// };
WebSocket客户端的API
浏览器对 WebSocket 协议的处理,无非就是三件事。
- 创建连接和断开连接。
- 发送信息和接收信息。
- 处理一些错误信息。
WebSocket对象的构造函数WebSocket()
通过构造函数,创建一个WebSocket对象。如下:
new WebSocket(url)
new WebSocket(url, protocols)
第一个参数url是WebSocket 服务器将要响应的 URL。
第二个参数protocols是可选的,不填就是默认。可以是单个字符串协议,也可以是多个字符串组成的数组。
const websocket = new WebSocket("ws://localhost:8080");
以上websocket对象就是刚创建的WebSocket对象,刚开始连,值不为空,一般表示已连接。
WebSocket对象的几大属性
binaryType
bufferedAmount
extensions
protocol
readyState
url
最主要的还是readyState属性,可以判断WebSocket连接的状态。
binaryType
WebSocket 连接接收的二进制数据的类型。
可以是blob
也可以是arraybuffer
bufferedAmount
实例对象的bufferedAmount
属性,表示还有多少字节的二进制数据没有发送出去。它可以用来判断发送是否结束。
var data = new ArrayBuffer(10000000);
socket.send(data);
if (socket.bufferedAmount === 0) {
// 发送完毕
} else {
// 发送还没结束
}
extensions
服务器选择的扩展名。
protocol
服务器选择的子协议的名称。
readyState
WebSocket 连接的当前状态。
分别有四种状态。
具体如下表所示:
值(value) | 状态 | 描述 |
---|---|---|
0 | CONNECTING | WebSocket已经创建好,但是连接还没打开 |
1 | OPEN | 表示连接成功,可以通信了 |
2 | CLOSING | 连接正在关闭进程中 |
3 | CLOSED | 连接已经关闭或者是打开连接失败 |
url
由构造函数解析的 WebSocket 的绝对 URL。
WebSocket对象还有两个实例方法。
1. close()
socket.close();
socket.close(code);
socket.close(code, reason);
主动关闭WebSocket连接。
第一个参数是关闭WebSocket连接的关闭码。不具体说明的话,是1000.
第二个参数就是关闭连接的理由。
2. send()
实例对象的send()
方法用于向服务器发送数据。
socket.send(data);
发送的数据可以是如下数据类型
string,ArrayBuffer
,Blob
,TypedArray
,DataView
如果连接只是刚创建,还没打开,就发送数据,会导致出现无效状态错误。
所以一定要等readyState的值为1时,才能发送数据。
WebSocket的监听事件
1. close
当WebSocket关闭连接时,触发close事件。
该事件有三个事件属性:
- code 关闭码
- reason 关闭连接理由
- wasClean 一个布尔值,是否已经关闭干净。
可以用以下两种方式监听:
addEventListener("close", (event) => {});
onclose = (event) => {};
socket.addEventListener("close", (event) => {
console.log("The connection has been closed successfully.");
});
socket.onclose = (event) => {
console.log("The connection has been closed successfully.");
};
2. error
当WebSocket发生错误时,触发error事件。
可以用以下两种方式监听:
addEventListener("error", (event) => {});
onerror = (event) => {};
// Create WebSocket connection
const socket = new WebSocket("ws://localhost:8080");
// Listen for possible errors
socket.addEventListener("error", (event) => {
console.log("WebSocket error: ", event);
});
3. message
当WebSocket接收到服务器的信息时,触发message事件。
接收到的数据也有好几个类型,可以是文本,二进制数据。
可以用以下两种方式监听:
addEventListener("message", (event) => {});
onmessage = (event) => {};
// Create WebSocket connection.
const socket = new WebSocket("ws://localhost:8080");
// Listen for messages
socket.addEventListener("message", (event) => {
console.log("Message from server ", event.data);
});
4. open
当WebSocket连接已经打开时,触发open事件。
可以用以下两种方式监听:
addEventListener("open", (event) => {});
onopen = (event) => {};
// Create WebSocket connection.
const socket = new WebSocket("ws://localhost:8080");
// Connection opened
socket.addEventListener("open", (event) => {
socket.send("Hello Server!");
});
总结
以上就是关于如何在客户端使用WebSocket的详细用法。文章来源:https://www.toymoban.com/news/detail-758919.html
参考链接:
WebSocket文章来源地址https://www.toymoban.com/news/detail-758919.html
到了这里,关于客户端 WebSocket详细用法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!