WebSocket的使用(nodejs)

8,092 阅读3分钟

WebSocket的使用(nodejs)

WebSocket介绍

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

img

WebSocket特点

  • 服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息
  • 建立在 TCP 协议之上,服务器端的实现比较容易。
  • 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  • 数据格式比较轻量,性能开销小,通信高效。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

WebSocket 事件

以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象(var Socket = new WebSocket(url, [protocol] );):

事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.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>