1. 程式人生 > >node socket 簡單聊天室

node socket 簡單聊天室

一、服務端

socket服務端接受來自客戶端的write內容(也可以理解成請求報文);然後廣播給先有連線的所有客戶端使用者client

const net = require("net");
const clients = [];
const port = 9999;
var client = net.createServer(socket=> {
    console.log(`server ${socket.remoteAddress} add in port ${port}`);
    clients.push(socket); //儲存連入的客戶
    //群聊資料處理
    function broadcast(signal,clients){
        let send = {
            protocal: signal.protocol,
            protocal: signal.from,
            protocal: signal.message,
        };
        //遍歷所有客戶端傳送
        clients.forEach(client => {
            client.write(JSON.stringify(send));
        })
    }
    //接受客戶端資料
    socket.on("data", (chunk) => {
        let signal = JSON.parse(chunk.toString().trim());
        let protocol = signal.protocal; 
        switch(protocol) {
            case "broadcast"://群聊
            broadcast(signal,clients);
            break;
            case "p2p"://私聊
            p2p(signal);
            break;
            default:
            socket.write("到底私聊還是群聊,你告訴我啊。。。");
        }

    })  
})


client.listen(port, (err) => {
    if(err) {throw new Error("埠被佔用,服務啟動失敗")};
    console.log(`server is listened on port ${port}`);
})

二、客戶端

const net = require("net");
const port = 9999;
const readline = require("readline");//用來讀取輸入行內容,api是有的,得找時間好好看看,據說可以逐行讀取檔案;

let rl = readline.createInterface(process.stdin, process.stdout);
rl.question("請輸入聊天室使用者名稱: "(name)=> {
    name = name.trim();
    //輸入名字了就建立連結
    let server = net.createConnection({port:port}, () => {
        //接受服務端的返回內容
        server.on("data", (chunk) => {
            let receive = JSON.parse(chunk.toString().trim());
            let protocol = receive.protocol;
            switch(protocol) {
                case "broadcast":
                console.log("\n" + receive.protocal);
                console.log(receive.from);
                console.log(receive.message);
                rl.prompt();
                break;
                //私聊
                case "p2p":
                .......//後面在寫
            }
        })
        rl.setPrompt(name + ">");
        rl.prompt(); //將輸入寫入到命令列;

        rl.on("line", (line) => {
            let send = {
                    protocol: "broadcast",
                    from: name,
                    message: line.toString().trim(),
                }
            //傳送輸入的訊息內容至服務端
            server.write(JSON.stringify(send));
        })
    })


})

小結:群聊是將接受內容遍歷傳送給每個儲存起來的socket客戶端物件,而私聊,需要根據輸入的內容判斷,是向誰私聊,然後點對點進行單個socket資料傳輸;

**可以加入線上人數,增加error事件監聽,監聽下線人數,當所有連線成功傳送,某一個客戶端突然出現傳送失敗,就可以簡單理解為下線(簡單理解,距離怎麼根據網路監聽線上下線還不知道。。。。)

**這只是在命令列中進行測試的案例,所以使用了readline模組。可以在html檔案中操作dom元素,增添輸入框,模擬一個聊天室的功能;後續試試;

**越努力,越幸運,加油