likes
comments
collection
share

node 使用websocket实现一个简易聊天

作者站长头像
站长
· 阅读数 16

使用nodejs实现一个简易版聊天程序.

client端

package.json

{
  "name": "client",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.2"
  }
}

server.js

const express = require("express");
const path = require("path");
const port = 4000;
const app = new express();

app.use(express.static(path.resolve(__dirname, "public")));


app.listen(port, () => {
    console.log(`Client server run at ${port}.`);
})

public/index.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>
        .chat {
            display: flex;
            flex-direction: column;
            row-gap: 10px;
        }

        .row {
            display: flex;
            width: 400px;
            column-gap: 10px;
        }

        #display {
            width: 100%;
            height: 300px;
            background-color: white;
            border: 1px solid black;
            overflow-y: auto;
        }

        #input {
            height: 100px;
            width: 400px;
        }
    </style>
</head>

<body>
    <div class="chat">
        <div class="row">
            <input id="sender" type="text" placeholder="发送方" />
            <button onclick="onConnect()">connect</button>
            <button onclick="onDisConnect()">disconnect</button>
            <button onclick="onClear()">clear</button>
        </div>
        <div class="row">
            <textarea id="display" readonly></textarea>
        </div>
        <div class="row">
            <textarea id="input" placeholder="发送消息"></textarea>
            <div>
                <input id="receiver" placeholder="接收方" />
                <button onclick="onSend()">send</button>
            </div>
        </div>
    </div>

    <script>
        let senderDom = document.getElementById("sender");
        let receiverDom = document.getElementById("receiver");
        let inputDom = document.getElementById("input");
        let displayDom = document.getElementById("display");
        let websocketIp = "ws://localhost:4005?name=";
        let ws;

        function onConnect() {
            if (ws) {
                onDisplay(`You are already online.`);
                return;
            }

            let sender = senderDom.value;
            ws = new WebSocket(websocketIp + sender);
            ws.onopen = (e) => {
                clearDisplay();
                onDisplay(`You are online.`);
            }

            ws.onclose = (e) => {
                onDisplay(`You are offline.`);
                ws = undefined;
            }

            ws.onmessage = (e) => {
                const obj = JSON.parse(e.data);
                const { type, data } = obj;

                if (type == "status") {
                    const { user, status } = data;
                    onDisplay(`${user} is ${status == 0 ? "offline" : "online"}.`);
                } else if (type == "message") {
                    const { sender, message } = data;
                    onDisplay(`${sender}:${message}`);
                }
            }
        }

        function onDisConnect() {
            if (!ws) {
                onDisplay(`You are offline,please connect first.`);
                return;
            }

            ws.close();
        }

        function onClear() {
            clearDisplay();
        }

        function onSend() {
            if (!ws) {
                onDisplay(`You are offline,please connect first.`);
                return;
            }

            let sender = senderDom.value;
            let receiver = receiverDom.value;
            let message = inputDom.value;
            let msg = JSON.stringify({ receiver: receiver, message: message });
            ws.send(msg);
            onDisplay(`${sender}:${message}`);
        }

        //utils
        function onDisplay(value) {
            displayDom.value += value + "\n\n";
            displayDom.scrollTop = displayDom.scrollHeight;
        }

        function clearDisplay() {
            displayDom.value = "";
        }

    </script>
</body>

</html>

server端

package.json

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.2",
    "ws": "^8.11.0"
  }
}

server.js

/**
 * 数据结构
 * get:
 * type message/status
 * data {sender,receriver,message}/{user,status: //0 offline 1 online}
 * 
 * send:
 * {receiver,message}
*/

const MESSAGE_TYPE = {
    MESSAGE: "message",
    STATUS: "status",
};

const STATUS = {
    ONLINE: 1,
    OFFLINE: 0,
}

const Websocket = require("ws");
const url = require("url");
const port = 4005;

const wss = new Websocket.Server({ port: port });

wss.on("connection", (ws, req) => {
    const parameters = url.parse(req.url, true);
    ws.name = parameters.query.name;

    //notice all the client that somebody is login
    wss.clients.forEach(client => {
        //skip self
        if (client.name == ws.name) {
            return;
        }

        let msg = JSON.stringify({
            type: MESSAGE_TYPE.STATUS,
            data: {
                status: STATUS.ONLINE,
                user: ws.name,
            }
        });
        client.send(msg)
    })

    ws.on("message", (e) => {
        const data = JSON.parse(e.toString());
        const { receiver } = data;
        wss.clients.forEach(client => {
            if (client.name == receiver) {
                let msg = JSON.stringify({
                    type: MESSAGE_TYPE.MESSAGE,
                    data: {
                        ...data,
                        sender: ws.name,
                    },
                })
                client.send(msg);
            }
        })
    })

    ws.on("close", (e) => {
        wss.clients.forEach(client => {
            let msg = JSON.stringify({
                type: MESSAGE_TYPE.STATUS,
                data: {
                    status: STATUS.OFFLINE,
                    user: ws.name,
                }
            });
            client.send(msg)
        })
    })
})

演示效果

node 使用websocket实现一个简易聊天