- A+
所属分类:Web前端
一、WebSocket概念
- WebSocket是HTML5提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议。它基于TCP传输协议,并复用HTTP的握手通道。浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接, 并进行双向数据传输。WebSocket 的出现就解决了半双工通信的弊端。它最大的特点是:服务器可以向客户端主动推动消息,客户端也可以主动向服务器推送消息。
二、WebSocket原理
- 客户端向 WebSocket 服务器通知(notify)一个带有所有接收者ID(recipients IDs)的事件(event),服务器接收后立即通知所有活跃的(active)客户端,只有ID在接收者ID序列中的客户端才会处理这个事件。
三、WebSocket特点
- 支持双向通信,实时性更强,相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少
- 可以发送文本,也可以发送二进制数据
- 建立在TCP协议之上,服务端的实现比较容易
- 数据格式比较轻量,性能开销小,通信高效
- 没有同源限制,客户端可以与任意服务器通信
- 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL
- 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器
四、WebSocket应用场景
- 弹幕
- 媒体聊天
- 协同编辑
- 基于位置的应用
- 体育实况更新
- 股票基金报价实时更新
五、Websocket基本使用
在HTML5中,浏览器已经实现了websocket的API,直接使用即可。
六、创建Websocket对象
// 参数1: url:连接的websocket属性 // 参数2: protocol,可选的,指定连接的协议 // var socket = new WebSocket('ws://echo.websocket.org') var Socket = new WebSocket(url, [protocol] );
七、Websocket事件
事件 | 事件处理程序 | 描述 |
---|---|---|
open | Socket.onopen | 连接建立时触发 |
message | Socket.onmessage | 客户端接收服务端数据时触发 |
error | Socket.onerror | 通信发生错误时触发 |
close | Socket.onclose | 连接关闭时触发 |
八、Websocket方法
方法 | 描述 |
---|---|
Socket.send() | 使用连接发送数据 |
Socket.close() | 关闭连接 |
使用nodejs开发websocket服务
我们刚刚使用了官网提供的echo服务,接下来我们自己通过nodejs实现一个简单的websocket服务。
使用nodejs开发websocket需要依赖一个第三方包。Nodejs Websocket
项目搭建
新建一个websocket server端的项目
mkdir server-demo cd server-demo yarn init -y yarn add nodejs-websocket touch app.js
开发服务程序
在app.js中
// 导入第三方模块 const ws = require('nodejs-websocket') // websocket占用的端口号 const PORT = 3000 const server = ws.createServer(connect => { console.log('新的连接') // 接收到客户端的文本内容时触发 connect.on('text', str => { console.log('接收:' + str) // 把接收到的字符串转换成大写,并且给客户端响应 connect.sendText(str.toUpperCase() + '!!!!') }) // 监听关闭事件 connect.on('close', () => { console.log('连接关闭了') }) // 监听错误事件, 比如浏览器关闭了连接,或者发送的数据格式不对等 connect.on('error', err => { console.log('连接异常') }) }) // 启动websocket服务 server.listen(PORT, function() { console.log(`websocket server listening on ${PORT}`) })
启动服务
node app.js
在终端中看到websocket server listening on 3000
就说明webserver服务启动成功了
进行测试
修改客户端中index.js
文件中的连接地址,重新进行测试
// 创建websocket对象,地址已经修改称为了自己编写的地址 const URL = 'ws://localhost:3000' const websocket = new WebSocket(URL)
九、案例-Websocket开发聊天室程序
app.js
const ws = require('nodejs-websocket') const PORT = 3000 const TYPE_MSG = 0 const TYPE_ENTER = 1 const TYPE_LEAVE = 2 let userCount = 0 const server = ws.createServer(connect => { console.log('有新用户连接了') // 每次有新用户连接,需要给所有用户发送一条新增用户的消息 userCount++ connect.userName = 'user' + userCount // 给所有的用户进行广播 broadcast({ type: TYPE_ENTER, msg: connect.userName + '进入了聊天室', date: new Date().toLocaleTimeString() }) connect.on('text', msg => { // 如果接收到用户的数据, 需要发送给所有的用户 broadcast({ type: TYPE_MSG, msg: msg, date: new Date().toLocaleTimeString() }) }) connect.on('close', () => { console.log('用户断开连接') userCount-- // 给所有的用户发送一条用户离开的消息 broadcast({ type: TYPE_LEAVE, msg: `${connect.userName}离开了聊天室`, date: new Date().toLocaleTimeString() }) }) connect.on('error', () => { console.log('连接失败') }) }) function broadcast(msg) { server.connections.forEach(conn => { conn.sendText(JSON.stringify(msg)) }) } server.listen(PORT, () => { console.log('服务器启动成功了', PORT) })
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> <style> /* div { width: 200px; height: 200px; border: 1px solid #000; } */ </style> </head> <body> <!-- 用于收集输入内容 --> <input type="text" placeholder="请输入需要发送的内容" /> <!-- 用于发送websocket请求 --> <button>websocket测试</button> <!-- 用于显示websock服务器的响应 --> <div class="show"></div> <script> var input = document.querySelector('input') var button = document.querySelector('button') var div = document.querySelector('div') // 1. 创建websocket对象, 这个地址是官方提供的地址 // var socket = new WebSocket('ws://echo.websocket.org') var socket = new WebSocket('ws://localhost:3000') // 2. 给websocket注册事件 socket.addEventListener('open', function() { // 与服务端建立连接的时候触发 div.innerText = '恭喜你,与服务端建立连接了' }) // 如何给服务器发送消息 button.addEventListener('click', function() { socket.send(input.value) input.value = '' }) // 如果接收服务器的数据 socket.addEventListener('message', function(e) { var data = JSON.parse(e.data) var dv = document.createElement('div') dv.innerHTML = data.msg + '----' + data.date if (data.type === 0) { dv.style.color = 'green' } if (data.type === 1) { dv.style.color = 'red' } if (data.type === 2) { dv.style.color = 'gray' } div.appendChild(dv) }) socket.addEventListener('close', () => { div.innerHTML = '与服务器断开连接' }) </script> </body> </html>
如果使用原生的websocket进行开发,会比较麻烦,比如支持的事件太少,发送的数据只能是字符串格式的,提供的api也很少,类似于广播这种方法都没有,需要自己封装。