簡(jiǎn)單聊天系統(tǒng)

之前在 f2e-server 里面做了一個(gè)有關(guān)監(jiān)聽(tīng)文件更新专挪,實(shí)時(shí)刷新預(yù)覽頁(yè)面的功能滩愁,基于這個(gè)原理做一個(gè)實(shí)時(shí)消息的推送檢測(cè)也是挺不錯(cuò)的谜叹。

  • 首先創(chuàng)建一個(gè)基本的HTTP服務(wù)器, 輸出javascript格式的文本數(shù)據(jù)
http.createServer(function (req, resp){
    var res = querystring.parse( url.parse(req.url).query );    // 格式化GET請(qǐng)求數(shù)據(jù)
    resp.writeHead(200, {"Content-Type": 'application/javascript'}); //輸出的mime-type是javascript
    resp.end( (res.callback || "callback") + '('+JSON.stringify(res)+');' ); //輸出結(jié)果咏窿,方法名可以是傳遞進(jìn)來(lái)的
}).listen(8973);
  • 服務(wù)端計(jì)劃僅使用query識(shí)別請(qǐng)求,不關(guān)心path路徑
    • name: "昵稱", // 消息發(fā)送來(lái)源, 昵稱
    • time: 1746389859, //接收從time時(shí)刻開(kāi)始的所有服務(wù)端消息
    • msg: "加入聊天室", //客戶端發(fā)出的消息
    • method: "pop" // pop-獲取消息素征;push-發(fā)送消息集嵌; exit-退出聊天室
    • msgList: [] //客戶端從服務(wù)端獲取的信息列表,附加在res上返回給客戶端
  • 完成基本的保存信息和信息輸出方法
function out(res, resp){
    resp.end( (res.callback || "callback") + '('+JSON.stringify(res)+');' );
}
function saveMsg(msg){
    mtime = msg.time = +new Date;
    list.push({  // list是所有信息列表
        name: msg.name,
        msg: msg.msg,
        time: mtime
    });
}
  • 根據(jù)不同情況識(shí)別發(fā)生事件
    • 如果沒(méi)有傳入時(shí)間御毅,或者請(qǐng)求類型不是GET根欧,或者沒(méi)有提供method參數(shù)
      識(shí)別為首次進(jìn)入聊天室,將msg參數(shù)修改成 "加入聊天室"亚享,保存記錄咽块,并且將結(jié)果輸出。
    if( !res.time || req.method === "POST" || !res.method ){
        res.msg = res.msg || "加入聊天室";
        res.msgList = [];
        saveMsg(res);
        out(res,resp);
    }
* 如果是消息提交欺税,直接將信息保存侈沪,也不用返回啥信息列表了,反正客戶端也用不著
else if( "push" === res.method ){
        saveMsg(res);
        out(res,resp);
    }
* 退出的時(shí)候晚凿,事實(shí)上也是進(jìn)行一個(gè)消息提交亭罪,只不過(guò)把msg修改成 **"離開(kāi)聊天室"**
else if( "exit" === res.method ){
        res.msg = "離開(kāi)聊天室";
        saveMsg(res);
        out(res,resp);
    }
* 其他情況識(shí)別為獲取信息列表,根據(jù)`res.time`返回?cái)?shù)據(jù)

這里是監(jiān)聽(tīng)更新的核心部分
1. 通過(guò)判斷提交的time和服務(wù)端最近更新時(shí)間mtime是否相等歼秽,
決定是否直接返回響應(yīng)時(shí)間范圍的消息列表应役。

if( res.time != mtime){
            res.msgList = list.filter(function(m){
                return m.time > res.time;
            });
            res.time = mtime;  // 更新time,返回給客戶端燥筷,客戶端每次獲取列表后更新本地的time參數(shù)
            out(res,resp);
        }
    2. 如果這兩個(gè)時(shí)間相等箩祥,500ms后繼續(xù)回調(diào)自己,回調(diào)夠60次肆氓,才返回一個(gè)空的消息列表袍祖。
else if(repeat >= 60){
            res.msgList = [];
            out(res,resp);
        }else{
            repeat++;
            setTimeout(getMsg,500);
        }
  • 數(shù)據(jù)信息的持久化
    事實(shí)上到這里,聊天系統(tǒng)的服務(wù)端已經(jīng)可用了谢揪,但是為了將所有的消息記錄都能在服務(wù)端存儲(chǔ)下來(lái)
    我們將list信息定時(shí)的存儲(chǔ)到文件里面:
function saveList(){
    if( mtime === stime ){ // stime 記錄上一次文件保存的時(shí)間
        // 如果最新修改都已經(jīng)保存,等待下次保存
    }else{  //否則更新存儲(chǔ)時(shí)間為最新修改時(shí)間
        stime = mtime; 
        var n = 0, tmp;
        while(list.length > 100){
            tmp = list.splice(0,100);  // 將list分割成100條一組蕉陋,存儲(chǔ)到指定文件名文件
            fs.writeFile( "data/"+stime+"-"+(n++)+".json", JSON.stringify(tmp,null,4) );
        } //剩下不夠100條的還存儲(chǔ)在基本文件下捐凭。
        fs.writeFile( "data.json", JSON.stringify(list,null,4) );
    }
    setTimeout(saveList, 1000*60*2);
}
saveList();
  • 客戶端代碼:
    • 發(fā)送消息
$("#form").on("submit",function(e){
        e.preventDefault();
        var data = {
            name: $("#name").val(),
            method:"push",
            msg: $("#msg").val()
        };
        $("#msg").val("");
        $.jsonp(root,data,function(d){
            console.log( '發(fā)送成功!' );
            $("#msg").focus();
        });
    });
* 接收消息
window.get = function(){
        $.jsonp(root,{
            name:$("#name").val(),
            method:"pop",
            time: time
        },function(d){
            time = d.time
            d.msgList.forEach(function(m){
                chat.append( $('<li></li>').text(m.name+":"+m.msg) );
            });
            window.get();
        });
    }
    window.get();
* 退出頁(yè)面
window.onbeforeunload = function(){
        $.jsonp(root,{
            name:$("#name").val(),
            method:"exit",
            time: time
        });
    };

PS:

在線聊天室: http://shy2850.github.io/wfQuery/demo/09.chatRoom.html
服務(wù)端完整代碼 https://github.com/shy2850/wfQuery/blob/master/demo/node/chat.js
客戶端代碼 https://github.com/shy2850/wfQuery/blob/master/demo/09.chatRoom.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凳鬓,一起剝皮案震驚了整個(gè)濱河市茁肠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缩举,老刑警劉巖垦梆,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蚁孔,居然都是意外死亡奶赔,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)杠氢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)站刑,“玉大人,你說(shuō)我怎么就攤上這事鼻百〗事茫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵温艇,是天一觀的道長(zhǎng)因悲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)勺爱,這世上最難降的妖魔是什么晃琳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮琐鲁,結(jié)果婚禮上卫旱,老公的妹妹穿的比我還像新娘。我一直安慰自己围段,他們只是感情好顾翼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著奈泪,像睡著了一般适贸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涝桅,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天拜姿,我揣著相機(jī)與錄音,去河邊找鬼冯遂。 笑死砾隅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的债蜜。 我是一名探鬼主播晴埂,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寻定!你這毒婦竟也來(lái)了儒洛?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤狼速,失蹤者是張志新(化名)和其女友劉穎琅锻,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體向胡,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恼蓬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了僵芹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片处硬。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拇派,靈堂內(nèi)的尸體忽然破棺而出荷辕,到底是詐尸還是另有隱情,我是刑警寧澤件豌,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布疮方,位于F島的核電站,受9級(jí)特大地震影響茧彤,放射性物質(zhì)發(fā)生泄漏骡显。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一曾掂、第九天 我趴在偏房一處隱蔽的房頂上張望惫谤。 院中可真熱鬧,春花似錦遭殉、人聲如沸石挂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)痹愚。三九已至,卻和暖如春蛔糯,著一層夾襖步出監(jiān)牢的瞬間拯腮,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工蚁飒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留动壤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓淮逻,卻偏偏與公主長(zhǎng)得像琼懊,于是被迫代替她去往敵國(guó)和親阁簸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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

  • github地址饶米,歡迎大家提交更新。 express() express()用來(lái)創(chuàng)建一個(gè)Express的程序车胡。ex...
    Programmer客棧閱讀 2,525評(píng)論 0 1
  • Address:https://www.zybuluo.com/XiangZhou/note/208532 Exp...
    天蠍蒗漫閱讀 11,318評(píng)論 2 55
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理檬输,服務(wù)發(fā)現(xiàn),斷路器匈棘,智...
    卡卡羅2017閱讀 134,672評(píng)論 18 139
  • 1.作用域javascript如同其他語(yǔ)言一樣同樣的有其作用域丧慈,我們把javascript的作用域可看做是自定的一...
    O8閱讀 344評(píng)論 0 0
  • 垂死病中驚坐起伊滋,渾渾噩噩又一年。過(guò)去的已過(guò)去队秩,將來(lái)的還未來(lái)笑旺,握住現(xiàn)在就好。不遺恨過(guò)去馍资,不希冀未來(lái)筒主,不畏懼現(xiàn)在∧裥罚看書(shū)...
    嵐風(fēng)的葉子閱讀 261評(píng)論 0 0