应用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)        })    })})

演示成果