使用原生node寫一個(gè)聊天室

在學(xué)習(xí)node的時(shí)候都會(huì)練習(xí)做一個(gè)聊天室的項(xiàng)目,主要使用socket.io模塊和http模塊坯屿。這里我們使用更加原始的方式去寫一個(gè)在命令行聊天的聊天室。

http模塊巍扛,socket.io都是高度封裝之后的模塊领跛,我們使用更加原始的net模塊來(lái)做。

socket

做聊天室撤奸,我們首先要了解一下socket吠昭,用百度百科上的定義:網(wǎng)絡(luò)上的兩個(gè)程序通過(guò)一個(gè)雙向的通信連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)連接的一端稱為一個(gè)socket胧瓜。socket對(duì)TCP/IP封裝提供網(wǎng)絡(luò)開(kāi)發(fā)的接口矢棚,提供網(wǎng)絡(luò)通信的接口。詳細(xì)可以看看各種百科的資料府喳。

服務(wù)端

1.基本接口介紹

創(chuàng)建服務(wù)端

const server = net.createServer((socket) => {
       //這里的毀掉函數(shù)中的參數(shù)就是一個(gè)socket
}
//監(jiān)聽(tīng)端口和主機(jī)
server.listen({
    port:4433,
    host:'127.0.0.1'//要想別人訪問(wèn)到蒲肋,要寫服務(wù)啟動(dòng)所在機(jī)子的ip地址,默認(rèn)localhost
}, () => {
    //這里是啟動(dòng)成功后的回調(diào)
    console.log('server bound')
})

服務(wù)創(chuàng)建成功之后钝满,socket可以提供客戶端(訪問(wèn)者)的一些信息兜粘,這里主要用的兩個(gè)屬性

socket.remoteAddress :客戶端的ip地址
socket.remotePort:客戶端訪問(wèn)的接口,這里是隨機(jī)分配弯蚜,注意這里的接口跟我們創(chuàng)建服務(wù)的接口不同孔轴,表示的意義也不一樣建立網(wǎng)絡(luò)通信連接至少要一對(duì)端口號(hào),服務(wù)端監(jiān)聽(tīng)的端口是為了跟服務(wù)端所在機(jī)子的其他服務(wù)區(qū)分碎捺,客戶端訪問(wèn)這個(gè)端口的時(shí)候自然也要區(qū)分路鹰,分配不同端口

socket的event事件

//監(jiān)聽(tīng)客戶端發(fā)送過(guò)來(lái)的消息
socket.on('data', (data) => {
      //這里data是一個(gè)buffer要轉(zhuǎn)化為字符串贷洲,然后去一下兩端空格
        let receive = JSON.parse(data.toString().trim());
    })
//給客戶端發(fā)送消息
socket.write(string[,encoding]);

錯(cuò)誤處理error

socket.on('error', (err) => {
      //在測(cè)試中發(fā)現(xiàn)晋柱,不去監(jiān)聽(tīng)這個(gè)錯(cuò)誤事件优构,當(dāng)你客戶端掉線之后服務(wù)端也會(huì)斷開(kāi)所以做一些錯(cuò)誤處理
    })
2.聊天設(shè)計(jì)
聊天過(guò)程我們分三部分

1.登錄
2.跟所有人聊
3.跟特定對(duì)象聊
首先我們確定聊天信息的發(fā)送格式,就像http里面有頭部趣斤,內(nèi)容等俩块。我們發(fā)送的信息,應(yīng)該包括發(fā)送者名字浓领,給誰(shuí)發(fā)以及發(fā)送的消息玉凯,設(shè)定為一下格式

const send = {
    name:"",
    message:"",
    to:""
}

服務(wù)端要根據(jù)給誰(shuí)發(fā)做不同的處理
1.登錄(login):我們要給所有的人發(fā)信息,XXX登錄了聊天室联贩,還要記錄這個(gè)訪問(wèn)的socket漫仆,以便于后續(xù)給特定的人發(fā)消息,格式{username:socket}

image.png

2.跟所有人聊天(server):除了發(fā)消息本人要給其他人發(fā)送
3.跟某一個(gè)人聊天(client):找到相應(yīng)的socket發(fā)送消息

socket.on('data', (data) => {
        let receive = JSON.parse(data.toString().trim());
        switch(receive.to){
            case "login":
                DealInfo.login(receive, socket);
                break;
            case "server":
                DealInfo.server(receive, socket);
                break;
            default:
                DealInfo.client(receive, socket);
                break;
        }
    })

之前我們有監(jiān)聽(tīng)socket的錯(cuò)誤處理泪幌,也就是當(dāng)用戶掉線的時(shí)候盲厌,我們就可以把記錄的socket刪除掉,并提示當(dāng)前用戶數(shù)祸泪。這里可以從記錄的socket個(gè)數(shù)求取吗浩,也可以根據(jù)以下方法

server.getConnections((err, count) => {
            if(err){
                throw err;
            }
            console.log(`${deleteKey}下線了 當(dāng)前在線人數(shù)${count}`);
        })
image.png

客戶端

1.基本接口介紹

創(chuàng)建socket連接

const client = net.connect({
            port:4433,
            host:'127.0.0.1'//默認(rèn)localhost
        }, () => {
              //連接成功之后的回調(diào)
        })

client的事件

//監(jiān)聽(tīng)服務(wù)端發(fā)送過(guò)來(lái)的信息
client.on('data', (data) => {
                //這里data是一個(gè)buffer
                let receive = JSON.parse(data.toString().trim());
            }).on('error', (err) => {
                //錯(cuò)誤處理
            })
//給服務(wù)端發(fā)送消息
client.wirte(string[, encoding]);
2.聊天設(shè)計(jì)
基本設(shè)置

登錄:要輸入聊天名再去連接客戶端
群聊或者跟某一個(gè)人聊只需要區(qū)分用戶即可,跟某一個(gè)人聊的輸入格式為name:message
聊天格式:name>message

2.1用戶名

這里我們使用readline這個(gè)模塊

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
rl.question('What is your name >', (name) => {
  //回調(diào)中的參數(shù)就所輸入的信息没隘,當(dāng)輸入非空的時(shí)候作為用戶名懂扼,之后按我們的聊天格式輸出預(yù)先樣式
    //設(shè)立設(shè)定prompt的輸出內(nèi)容,只要調(diào)用rl.prompt()即可
    rl.setPrompt(`${name.trim()}>`);
    rl.prompt();
}
Paste_Image.png

監(jiān)聽(tīng)用戶輸入

 rl.on('line', (line) => {
                let stdinInfo = line.trim().split(':');
                if(stdinInfo.length == 2){
                    //跟某個(gè)用戶聊天
                    send.to = stdinInfo[0];
                    send.message = stdinInfo[1];
                }else{
                    //跟所有人聊天
                    send.to = "server";
                    send.message = stdinInfo[0];
                }
                client.write(JSON.stringify(send));
                rl.prompt();
            })
Paste_Image.png

詳細(xì)代碼地址:https://github.com/Stevenzwzhai/node-socket-chatroom

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末右蒲,一起剝皮案震驚了整個(gè)濱河市阀湿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑰妄,老刑警劉巖陷嘴,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異间坐,居然都是意外死亡灾挨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門眶诈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)涨醋,“玉大人,你說(shuō)我怎么就攤上這事逝撬≡÷睿” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵宪潮,是天一觀的道長(zhǎng)溯警。 經(jīng)常有香客問(wèn)我趣苏,道長(zhǎng),這世上最難降的妖魔是什么梯轻? 我笑而不...
    開(kāi)封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任食磕,我火速辦了婚禮,結(jié)果婚禮上喳挑,老公的妹妹穿的比我還像新娘彬伦。我一直安慰自己,他們只是感情好伊诵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布单绑。 她就那樣靜靜地躺著,像睡著了一般曹宴。 火紅的嫁衣襯著肌膚如雪搂橙。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天笛坦,我揣著相機(jī)與錄音区转,去河邊找鬼。 笑死版扩,一個(gè)胖子當(dāng)著我的面吹牛废离,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播礁芦,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼厅缺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了宴偿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤诀豁,失蹤者是張志新(化名)和其女友劉穎窄刘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體舷胜,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡娩践,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烹骨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翻伺。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖沮焕,靈堂內(nèi)的尸體忽然破棺而出吨岭,到底是詐尸還是另有隱情,我是刑警寧澤峦树,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布辣辫,位于F島的核電站旦事,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏急灭。R本人自食惡果不足惜姐浮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望葬馋。 院中可真熱鬧卖鲤,春花似錦、人聲如沸畴嘶。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)掠廓。三九已至换怖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蟀瞧,已是汗流浹背沉颂。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悦污,地道東北人铸屉。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像切端,于是被迫代替她去往敵國(guó)和親彻坛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容