websocket的使用

203 阅读1分钟

什么是websocket

WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信,位于OSI模型的应用层,是H5新增的 API。

  • TCP连接,与HTTP协议兼容(一个项目里面即可有http协议,又可以有ws)
  • 双向通信,主动推送(服务端向客户端)
  • 无同源限制,协议标识符是ws(加密wss,没有跨域的限制)

websocket应用场景

  • 聊天、消息、点赞
  • 直播评论(弹幕)
  • 游戏、协同编辑、基于未知的应用

基本使用 html部分代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #messagebox {
            width: 300px;
            height: 300px;
            border: 1px solid #000;
        }
    </style>
</head>


<body>
    <div>
        <input type="text" placeholder="请输入您的消息" />
        <button>发送消息</button>
        <div id="messagebox"></div>
    </div>
    <script>
        var input = document.querySelector('input');
        var button = document.querySelector('button');
        var msgBox = document.querySelector('#messagebox');
        console.log(input);
        console.log(button);
        console.log(msgBox);
        const ws = new WebSocket("ws://localhost:8080");
        button.addEventListener('click', function () {
            console.log('click')
        })
        
        // ws事件监听
        ws.addEventListener('open', function () {
            console.log('连接成功了')
        })

        ws.addEventListener('message', function (e) {
            console.log(e)
        })
        ws.addEventListener('close', function () {
            console.log('连接关闭')
        })

        ws.addEventListener('error', function () {
            console.log('连接异常')
        })

    </script>
</body>

</html>

基本使用 node部分

yarn add nodejs-websocket

const ws = require('nodejs-websocket');

const server = ws.createServer((conn) => {
    console.log('有人连接上来了')
    
    conn.on('error', () => {
        console.log('连接异常!!!')
    })
})

server.listen(8080, () => {
    console.log('websocket服务启动成功了,监听了端口8080');
})


发送消息并且展示到页面上

<!DOCTYPE html>
<html lang="en">


<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #messagebox {
            width: 300px;
            height: 300px;
            border: 1px solid #000;
        }
    </style>
</head>


<body>
    <div>
        <input type="text" placeholder="请输入您的消息" />
        <button>发送消息</button>
        <div id="messagebox"></div>
    </div>
    <script>
        var input = document.querySelector('input');
        var button = document.querySelector('button');
        var msgBox = document.querySelector('#messagebox');
        console.log(input);
        console.log(button);
        console.log(msgBox);


        const ws = new WebSocket("ws://localhost:8080");
        
        button.addEventListener('click', function () {
            // console.log(input.value)
            let value = input.value
            ws.send(value)
        })
        // ws事件监听
        ws.addEventListener('open', function () {
            console.log('连接成功了')
        })


        ws.addEventListener('message', function (e) {
            console.log(e,'message')
            let data = e.data;
            let div = document.createElement('div')
            div.innerHTML = `${data}`;
            msgBox.appendChild(div)
            input.value = ''
        })
        ws.addEventListener('close', function () {
            console.log('连接关闭')
        })


        ws.addEventListener('error', function () {
            console.log('连接异常')
        })


    </script>
</body>


</html>
const ws = require('nodejs-websocket');


const server = ws.createServer(connect => {
    console.log('有用户连接上来了');
    connect.on('text', data => {
        console.log('接收到了用户的数据', data);
        // 2.2 给用户一个响应的数据
        connect.send(data);
    })
    // 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
    connect.on("close", function (code, reason) {
        console.log("用户关闭链接")
    })
    // 注册一个error,处理用户的报错信息
    connect.on('error', () => {
        console.log('用户连接异常')
    })
})


server.listen(8080, () => {
    console.log('websocket服务启动成功了,监听了端口8080');
})

添加广播事件

让所有人接收到消息

const ws = require('nodejs-websocket');


const server = ws.createServer(connect => {
    console.log('有用户连接上来了');
    connect.on('text', data => {
        console.log('接收到了用户的数据', data);
        // 2.2 给用户一个响应的数据
        // connect.send(data);
        broadcast(data);
    })
    // 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
    connect.on("close", function (code, reason) {
        console.log("用户关闭链接")
    })
    // 注册一个error,处理用户的报错信息
    connect.on('error', () => {
        console.log('用户连接异常')
    })
})


// 广播消息
function broadcast(data) {
    server.connections.forEach(item => {
        item.send(data)
    })
}


server.listen(8080, () => {
    console.log('websocket服务启动成功了,监听了端口8080');
})

简单聊天室

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #messagebox {
            width: 300px;
            height: 300px;
            border: 1px solid #000;
        }
    </style>
</head>


<body>
    <div>
        <input type="text" placeholder="请输入您的消息" />
        <button>发送消息</button>
        <div id="messagebox"></div>
    </div>
    <script>
        var input = document.querySelector('input');
        var button = document.querySelector('button');
        var msgBox = document.querySelector('#messagebox');
        console.log(input);
        console.log(button);
        console.log(msgBox);


        const ws = new WebSocket("ws://localhost:8080");


        button.addEventListener('click', function () {
            // console.log(input.value)
            let value = input.value
            ws.send(value)
        })
        // ws事件监听


        ws.addEventListener('open', function () {
            console.log('连接成功了')
        })


        ws.addEventListener('message', function (e) {
            console.log(e,'message')
            let data = e.data;
            let div = document.createElement('div')
            div.innerHTML = `${data}`;
            msgBox.appendChild(div)
            input.value = ''
        })
        ws.addEventListener('close', function () {
            console.log('连接关闭')
        })


        ws.addEventListener('error', function () {
            console.log('连接异常')
        })


    </script>
</body>


</html>
const ws = require('nodejs-websocket');


// 记录当前连接上来多少个人
let count = 0;
const server = ws.createServer(connect => {
    console.log('有用户连接上来了');
    count++;
    connect.userName = `用户${count}`
    broadcast(`${connect.userName}进入了聊天室`);
    connect.on('text', data => {
        console.log('接收到了用户的数据', data);
        // 2.2 给用户一个响应的数据
        // connect.send(data);
        broadcast(`${connect.userName}:${data}`);
    })
    // 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
    connect.on("close", function (code, reason) {
        console.log("用户关闭链接")
        broadcast(`${connect.userName}离开了聊天室`);
        count--;
    })
    // 注册一个error,处理用户的报错信息
    connect.on('error', () => {
        console.log('用户连接异常')
    })
})


// 广播消息
function broadcast(data) {
    server.connections.forEach(item => {
        item.send(data)
    })
}


server.listen(8080, () => {
    console.log('websocket服务启动成功了,监听了端口8080');
})

复杂聊天室

const ws = require('nodejs-websocket');
const TYPE_ENTER = 0;  // 进入消息
const TYPE_LEAVE = 1;  // 离开消息
const TYPE_MSG = 2;    // 聊天消息
// 记录当前连接上来多少个人
let count = 0;
const server = ws.createServer(connect => {
    console.log('有用户连接上来了');
    count++;
    connect.userName = `用户${count}`
    broadcast({
        type: TYPE_ENTER,
        msg: `${connect.userName}:进入了聊天室`,
        time: new Date().toLocaleTimeString()
    })


    connect.on('text', data => {
        console.log('接收到了用户的数据', data);
        // 2.2 给用户一个响应的数据
        // connect.send(data);
        // broadcast(`${connect.userName}:${data}`);
        broadcast({
            type: TYPE_MSG,
            msg: `${connect.userName}:${data}`,
            time: new Date().toLocaleTimeString()
        })
    })
    // 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
    connect.on("close", function (code, reason) {
        console.log("用户关闭链接")
        // broadcast(`${connect.userName}离开了聊天室`);
        broadcast({
            type: TYPE_LEAVE,
            msg: `${connect.userName}:离开了聊天室`,
            time: new Date().toLocaleTimeString()
        })
        count--;
    })
    // 注册一个error,处理用户的报错信息
    connect.on('error', () => {
        console.log('用户连接异常')
    })
})


// 广播消息
function broadcast(data) {
    server.connections.forEach(item => {
        item.send(JSON.stringify(data))
    })
}


server.listen(8080, () => {
    console.log('websocket服务启动成功了,监听了端口8080');
})
<!DOCTYPE html>
<html lang="en">


<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #messagebox {
            width: 300px;
            height: 300px;
            border: 1px solid #000;
        }
    </style>
</head>


<body>
    <div>
        <input type="text" placeholder="请输入您的消息" />
        <button>发送消息</button>
        <div id="messagebox"></div>
    </div>
    <script>
        const TYPE_ENTER = 0;  // 进入消息
        const TYPE_LEAVE = 1;  // 离开消息
        const TYPE_MSG = 2;    // 聊天消息


        var input = document.querySelector('input');
        var button = document.querySelector('button');
        var msgBox = document.querySelector('#messagebox');


        const ws = new WebSocket("ws://localhost:8080");
        button.addEventListener('click', function () {
            // console.log(input.value)
            let value = input.value
            ws.send(value)
        })
        // ws事件监听


        ws.addEventListener('open', function () {
            console.log('连接成功了')
        })


        ws.addEventListener('message', function (e) {
            console.log(e, 'message')
            let data = JSON.parse(e.data);
            console.log(data);
            let div = document.createElement('div')
            div.innerHTML = `${data.msg}---${data.time}`;
            if (data.type === TYPE_ENTER) {
                div.style.color = 'green';
            } else if (data.type === TYPE_MSG) {
                div.style.color = 'blue'
            } else {
                div.style.color = 'red'
            }
            msgBox.appendChild(div)
            input.value = ''
        })
        ws.addEventListener('close', function () {
            console.log('连接关闭')
        })


        ws.addEventListener('error', function () {
            console.log('连接异常')
        })


    </script>
</body>


</html>

聊天记录左右展示

自己右,其他人左

安装依赖

js npm install uuid

node部分代码

    const ws = require('nodejs-websocket');
    const { v4: uuidv4 } = require('uuid');

    const TYPE_ENTER = 0;  // 进入消息
    const TYPE_LEAVE = 1;  // 离开消息
    const TYPE_MSG = 2;    // 聊天消息

    // 记录当前连接上来多少个人
    let count = 0;
    const server = ws.createServer(connect => {
        console.log('有用户连接上来了');
        count++;
        connect.userName = `用户${count}`;
        connect.uuid = uuidv4();
        broadcast({
            userName: connect.userName,
            uuid: connect.uuid,
            type: TYPE_ENTER,
            msg: `${connect.userName}:进入了聊天室`,
            time: new Date().toLocaleTimeString()
        })

        connect.on('text', data => {
            console.log('接收到了用户的数据', data);
            // 2.2 给用户一个响应的数据
            // connect.send(data);
            // broadcast(`${connect.userName}:${data}`);
            broadcast({
                userName: connect.userName,
                uuid: connect.uuid,
                type: TYPE_MSG,
                msg: `${connect.userName}${data}`,
                time: new Date().toLocaleTimeString()
            })
        })
        // 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
        connect.on("close", function (code, reason) {
            console.log("用户关闭链接")
            // broadcast(`${connect.userName}离开了聊天室`);
            broadcast({
                type: TYPE_LEAVE,
                msg: `${connect.userName}:离开了聊天室`,
                time: new Date().toLocaleTimeString()
            })
            count--;
        })
        // 注册一个error,处理用户的报错信息
        connect.on('error', () => {
            console.log('用户连接异常')
        })
    })

       // 广播消息
      function broadcast(data) {
        server.connections.forEach(item => {
            item.send(JSON.stringify(data))
        })
      }


      server.listen(8080, () => {
        console.log('websocket服务启动成功了,监听了端口8080');
     })

html部分代码
根据ws监听拿到后端传递过来的数据,判断聊天进入离开的状态,给消息加上文字颜色,方便区分.

  <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            #messagebox {
                width: 400px;
                height: 200px;
                border: 1px solid #000;
                overflow: auto;
            }

            .clearfloat:after {
                display: block;
                clear: both;
                content: "";
                visibility: hidden;
                height: 0
            }

            .msg-right {
                text-align: right;
            }

            .msg-left {
                text-align: left;
            }
        </style>
    </head>
    <body>
        <div>
            <input type="text" placeholder="请输入您的消息" />
            <button>发送消息</button>
            <div id="messagebox" class="clearfloat"></div>
        </div>
        <script>
            const TYPE_ENTER = 0;  // 进入消息
            const TYPE_LEAVE = 1;  // 离开消息
            const TYPE_MSG = 2;    // 聊天消息

            let flag = true;
            var input = document.querySelector('input');
            var button = document.querySelector('button');
            var msgBox = document.querySelector('#messagebox');

            const ws = new WebSocket("ws://localhost:8080");
            button.addEventListener('click', function () {
                // console.log(input.value)
                let value = input.value
                ws.send(value)
            })
            // ws事件监听

            ws.addEventListener('open', function () {
                console.log('连接成功了')
            })

            ws.addEventListener('message', function (e) {
                // console.log(e, 'message')
                let data = JSON.parse(e.data);
                console.log(data);
                let div = document.createElement('div')
                div.style.marginBottom = '8px';
                div.innerHTML = `${data.msg}---${data.time}`;
                if (data.type === TYPE_ENTER) {
                    div.style.color = 'green';
                    if (flag) {
                        sessionStorage.setItem(data.uuid, data.userName)
                        flag = false
                    };
                } else if (data.type === TYPE_MSG) {
                    div.style.color = 'blue'
                    let name = sessionStorage.getItem(data.uuid);
                    div.classList.add("msg-left");
                    if (data.userName === name) {
                        div.classList.remove("msg-left");
                        div.classList.add("msg-right");
                    }
                } else {
                    div.style.color = 'red'
                }
                msgBox.appendChild(div)
                input.value = ''
            })
            ws.addEventListener('close', function () {
                console.log('连接关闭')
            })

            ws.addEventListener('error', function () {
                console.log('连接异常')
            })

        </script>
    </body>
    </html>

 

绑定enter按键

通过监听body的键盘按下事件,判断 e.keycode值为13时(enter键)时,触发button按钮的事件 完成绑定键盘事件

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            #messagebox {
                width: 400px;
                height: 200px;
                border: 1px solid #000;
                overflow: auto;
            }

            .msg-right {
                text-align: right;
            }

            .msg-left {
                text-align: left;
            }
        </style>
    </head>
    <body>
        <div>
            <input type="text" placeholder="请输入您的消息" />
            <button>发送消息</button>
            <div id="messagebox"></div>
        </div>
        <script>
            const TYPE_ENTER = 0;  // 进入消息
            const TYPE_LEAVE = 1;  // 离开消息
            const TYPE_MSG = 2;    // 聊天消息

            var body = document.querySelector('body')
            var input = document.querySelector('input');
            var button = document.querySelector('button');
            var msgBox = document.querySelector('#messagebox');

            const ws = new WebSocket("ws://localhost:8080");
            button.addEventListener('click', function () {
                // console.log(input.value)
                let value = input.value
                input.value !== '' && ws.send(value)
            })

            body.addEventListener('keydown', function (event) {
                if (input.value !== '' && event.keyCode === 13) {
                    button.click();
                }
            })
            // ws事件监听
            ws.addEventListener('open', function () {
                console.log('连接成功了')
            })
            let flag = true;
            ws.addEventListener('message', function (e) {
                // console.log(e, 'message')
                let data = JSON.parse(e.data);
                console.log(data);
                let div = document.createElement('div')
                div.innerHTML = `${data.msg}---${data.time}`;
                if (data.type === TYPE_ENTER) {
                    div.style.color = 'green';
                    if (flag) {
                        sessionStorage.setItem(data.uuid, data.userName)
                        flag = false;
                    }
                } else if (data.type === TYPE_MSG) {
                    div.style.color = 'blue'
                    let name = sessionStorage.getItem(data.uuid)
                    div.classList.add("msg-left");
                    if (data.userName === name) {
                        div.classList.remove("msg-left");
                        div.classList.add("msg-right");
                    }
                } else {
                    div.style.color = 'red'
                }
                msgBox.appendChild(div)
                input.value = ''
            })
            ws.addEventListener('close', function () {
                console.log('连接关闭')
            })

            ws.addEventListener('error', function () {
                console.log('连接异常')
            })
        </script>
    </body>
    </html>

自动滚动聊天记录到底部

触发scrollIntoView 可以在发送消息满屏触底时,超出屏幕可以自动滚动到底部。

 div.scrollIntoView({ block: "end", inline: "nearest", behavior: 'smooth' });