WebSocket的使用(nodejs)
WebSocket介绍
- WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。允许服务端主动向客户端推送数据(HTTP 协议有一个缺陷:通信只能由客户端发起)。
- 在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
- Ajax轮询:即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。

WebSocket特点
- 服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息
- 建立在 TCP 协议之上,服务器端的实现比较容易。
- 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
- 数据格式比较轻量,性能开销小,通信高效。
- 可以发送文本,也可以发送二进制数据。
- 没有同源限制,客户端可以与任意服务器通信。
- 协议标识符是
ws(如果加密,则为wss),服务器网址就是 URL。
WebSocket 事件
以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象(var Socket = new WebSocket(url, [protocol] );):
| 事件 | 事件处理程序 | 描述 |
|---|---|---|
| open | Socket.onopen | 连接建立时触发 |
| message | Socket.onmessage | 客户端接收服务端数据时触发 |
| error | Socket.onerror | 通信发生错误时触发 |
| close | Socket.onclose | 连接关闭时触发 |
WebSocket 方法
以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:
| 方法 | 描述 |
|---|---|
| Socket.send() | 使用连接发送数据 |
| Socket.close() | 关闭连接 |
WebSocket简单案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WenSocket</title>
<style>
div{
width: 200px;
height: 200px;
border:1px solid;
margin-top: 5px;
}
</style>
</head>
<body>
<input type="text" placeholder="请输入内容">
<button>提交</button>
<div></div>
<script>
const input = document.querySelector('input')
const button = document.querySelector('button')
const div = document.querySelector('div')
//创建WebSocket实例
const socket = new WebSocket("ws://echo.websocket.org")
//监听服务是否链接
socket.addEventListener('open',()=>{
div.innerHTML = "服务链接成功"
})
//button触发点击事件,将input框中的内容发送至websocket
//查看websocket是否接收到数据:chrome F12打开控制台》Network》WS》echo.websocket.org》messages
button.addEventListener('click',()=>{
const value = input.value
socket.send(value)
})
// 将接收到的数据插入到div中
socket.addEventListener('message',(e)=>{
console.log(e)
div.innerHTML = e.data
})
</script>
</body>
</html>
使用Node搭建websocket服务
-
安装模块:yarn add nodejs-websocket
-
配置服务(www.npmjs.com/package/nod… socket = new WebSocket("ws://echo.websocket.org")
改为const socket = new WebSocket("ws://localhost:3000")`var ws = require("nodejs-websocket") // 创建一个服务server,每次用户链接,函数就会被执行,并给当前用户创建一个connect对象 var server = ws.createServer(connect => { // 每当接收到用户传递过来的数据,就会触发text事件,并传入数据 connect.on("text", data => { // 给用户响应数据 // connect.sendText(data.toUpperCase()+"!!!") //转换大小写并并拼接字符串 connect.send(data) }) //监听websocket断开链接 connect.on("close", () => { console.log("websocket连接断开....") }) //监听websocket异常信息 connect.on("error", () => { console.log("websocket连接异常....") }) }) server.listen(3000, () => { console.log("websocket running") })
WebSocket聊天室
聊天室基本功能搭建
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WenSocket</title>
<style>
</style>
</head>
<body>
<input type="text" placeholder="请输入内容">
<button>提交</button>
<div></div>
<script>
const input = document.querySelector('input')
const button = document.querySelector('button')
const div = document.querySelector('div')
const socket = new WebSocket('ws://localhost:3000')
socket.addEventListener('open',()=>{
div.innerText = "欢迎来到聊天室"
})
button.addEventListener('click',()=>{
const value = input.value
socket.send(value)
input.value = ''
})
socket.addEventListener('message',(e)=>{
//div.innerText = e.data //这种方法会覆盖原先的数据
const dv = document.createElement('div')
dv.innerText = e.data
div.appendChild(dv)
})
</script>
</body>
</html>
优化——为不同类型信息添加颜色
app.js
const ws =require('nodejs-websocket')
// 统计用户数,每当用户访问,函数就会被执行,并给用户创建conncet对象
var count = 0
/* 主要修改代码----- **/
/*
type:消息类型 ,0 : 表示加入聊天室的消息, 1 : 表示用户离开聊天室的消息, 2 : 正常的聊天消息
**/
const TYPE_ENTER = 0
const TYPE_LEAVE = 1
const TYPE_MSG = 2
/* ------主要修改代码 **/
const server = ws.createServer(connect=>{
count++
connect.userName = `用户${count}`
/* 主要修改代码----- **/
broadcast({
type: TYPE_ENTER,
msg: `${connect.userName}进来了`,
time: new Date().toLocaleTimeString()
})
/* ------主要修改代码 **/
connect.on('text',data=>{
// connect.send(data) send 只为当前用户发送数据
/* 主要修改代码----- **/
broadcast({
type: TYPE_MSG,
msg: data,
time: new Date().toLocaleTimeString()
})
})
/* ------主要修改代码 **/
connect.on('close',()=>{
/* 主要修改代码----- **/
broadcast({
type: TYPE_LEAVE,
msg: `用户${count}离开了`,
time: new Date().toLocaleTimeString()
})
/* ------主要修改代码 **/
count--
console.log('连接关闭。。。')
})
connect.on("error",()=>{
console.log('连接异常。。。。')
})
})
//An Array with all connected clients. It's useful for broadcasting a message
function broadcast(msg) {
server.connections.forEach((connect)=> {
connect.send(JSON.stringify(msg))
})
}
server.listen(3000,()=>{
console.log('websocket running.....')
})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WenSocket</title>
<style>
</style>
</head>
<body>
<input type="text" placeholder="请输入内容">
<button>提交</button>
<div></div>
<script>
const input = document.querySelector('input')
const button = document.querySelector('button')
const div = document.querySelector('div')
const socket = new WebSocket('ws://localhost:3000')
/* 主要修改代码----- **/
const TYPE_ENTER = 0
const TYPE_LEAVE = 1
const TYPE_MSG = 2
/* ------主要修改代码 **/
socket.addEventListener('open', () => {
div.innerText = "欢迎来到聊天室"
})
button.addEventListener('click', () => {
const value = input.value
socket.send(value)
input.value = ''
})
socket.addEventListener('message', (e) => {
// div.innerText = e.data
/* 主要修改代码----- **/
const data = JSON.parse(e.data)
/* ------主要修改代码 **/
// console.log(data)
const dv = document.createElement('div')
/* 主要修改代码----- **/
dv.innerText = data.msg+"-----"+data.time
if(data.type===TYPE_ENTER){
dv.style.color = '#28dab4'
}
else if(data.type===TYPE_LEAVE){
dv.style.color = '#ff0707'
}else if(data.type===TYPE_MSG){
dv.style.color = '#000000'
}
/* ------主要修改代码 **/
div.appendChild(dv)
})
</script>
</body>
</html>