nodeJS+express+Jade寫一個局域網聊天應用(node基礎)

  爲了複習一下nodeJS, 並且socketIO這東西聽起來就好高端有木有, 並且有人寫過了open, 也能夠做爲本身的參考有木有, 點擊下載源代碼javascript

  express是4.x的版本, 跟之前的配置有些區別, 我才無論呢, 好用就好>﹏<;html

  按照正常的流程經過 node install 安裝項目依賴, 項目的依賴以下;java

  "dependencies": {
    "body-parser": "~1.8.4",
    "cookie-parser": "~1.3.3",
    "debug": "~2.0.0",
    "express": "~4.9.8",
    "jade": "~1.6.0",
    "morgan": "~1.3.2",
    "serve-favicon": "~2.1.7",
    "socket.io": "~1.2.1"
  }

  (若是你像本身建項目的話 直接在命令行下 執行express projectName, express就會爲你自動新建一個項目;)node

  先來看下高大上的服務端截圖;web

  

  

  酷炫的客戶端截圖:chrome

  

 

  客戶端的主要功能是發送消息, 若是用戶不輸入名字後臺會分配一個名字給客戶端;express

  服務端的主要功能是處理用戶發送的數據, 而後把數據保存到json,  同時再把當前的新數據推送到全部 , 有鏈接到當前socket服務器的客戶端;json

 

  簡單的服務端流程以下:數組

//獲取對應的依賴
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var http = require("http");
//主要就是經過socketIO的實現消息的實時推送;
var socketIo = require("socket.io");
//原生fileSystem模塊,把數據保存起來的和獲取數據用的;
var fs = require("fs");

....


var app = express();
var server = http.createServer(app);
//把socketIO綁定到服務上;
io = socketIo( server );
io.on('connection', function (socket) {
    //socket的各類事件寫在這邊;
})
//啓動服務, 監聽的端口設置在3000;
server.listen( 3000 , function() {
    console.log(" server is created ");
});


//使用jade模板, 以及設定視圖目錄;
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

    服務端裏面使用了封裝了一個fs進行簡單的文件操做,包括讀取和寫入的方法, 爲了保存數據用的; 服務器

  socket主要的幾個事件要知道,包括:

//這個是socketIO初始化時候的事件;
io.on('connection', function (socket) {
    //客戶端發送 message給服務端的時候的事件, 用戶發送過消息這個會觸發;
    socket.on('message', function(msg){});
    socket.on('disconnect', function (msg) {});
    //給當前鏈接的客戶端回傳一條消息;
    socket.emit("message",{});
    //給非當前的全部用戶發送推送消息;
    socket.broadcast.emit("message",{});
    //你能夠給客戶端發送各類事件,名字你找本身起;
    socket.emit('open',"sb");
    socket.emit('hehe',"sb");
    socket.emit('cnblogs',"sb");
});

 

  全部的服務端代碼(app.js)

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var http = require("http");
var socketIo = require("socket.io");
var fs = require("fs");

var routes = require('./routes/index');
//var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
//app.use('port', process.env.PORT || 3000);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
//app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
};

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});
var server = http.createServer(app);
/*
var server = http.createServer(function(req, res){
    res.end("hehe");
});
 */
io = socketIo( server );

var clients = {};
var appUtil = require("util")._extend({},{
    getRandomId : function() {
        var i=0;
        i++;
        return function() {
            return "name"+(i++);
        }
    }(),
    read : function( callback ) {
        /*
         *   data.json保存的數據結構爲 { key:[] Array };
         * */
        fs.readFile("data/data.json",function(err,data){
            data = data.toString();
            callback( JSON.parse(data).key );
        });
    },
    write : function( writeData ,callback ) {
        //讀取數據並重寫數據;
        this.read(function(data) {
            //我這個node讀取單個json會返回一個a字符串,我就笑了,什麼狀況
            // 若是你直接把json放在數組裏面就沒有這個問題;
            //data = data[0] === "a" ? data.slice(1) : data;
            data.push( writeData );
            var temp = {
                key : data
            };
            fs.writeFileSync("data/data.json",JSON.stringify(temp));
            callback()
        });
    }
});

/*
 *   @desc WebSocket API, 端口3000, msg爲對象:
 *   @param {  } 傳遞空對象會返回 {msg : 讀取文件的結果 JSON, name : 隨機的一個name};
 *   @param { name : "xx" , type : "get" , msg :  string }; //msg 讀取文件的結果, type獲取的類型
 *   @param { name : "xx" , type : "add" , msg : string }; //type 是 add爲 添加, msg是指要添加的消息;
 */

 io.on('connection', function (socket) {
     socket.emit('open',"laile");//通知客戶端已鏈接

     // 這個閉包內的工具方法;
     var sendMessage = function(name) {
         appUtil.read(function(data) {

             //給當前鏈接的用戶發送sock消息
             socket.emit("message",{
                 name : name,
                 msg : data
             });
             //給非當前的全部用戶發送消息;
             socket.broadcast.emit("message",{
                 name : name,
                 msg : data
             });
         });
     };

     socket.on('message', function(msg){
        console.log("來消息了");
        console.log(msg);
        //若是是沒有name的,咱們會分配一條name給用戶;
         var name = msg.name || appUtil.getRandomId();

        if(!msg.name) {
            sendMessage( name );
            clients[name] = true;
        }else if(msg.type == "get") {
            sendMessage(name);
        }else if( msg.type == "add" ) {
            //我勒個去,由於readFile和appendFile是異步的, 因此要添加回調, 固然, 你能夠用同步的readFileSync;
            appUtil.write({ time : new Date().toString(),  "name" : msg.name,  "msg" : msg.msg}, function(){
                sendMessage(name);
            });
        };

         //若是是新用戶的話, 廣播一條叫作新用戶登錄的信息;
         console.log(name)
         if(!clients[name]) {
             clients[name] = true;
             console.log("廣播新用戶登陸的消息");
             //注意 : 這個是socket,不是msg;
             socket.broadcast.emit("refreshUser",name);
         };
     });

     socket.on('disconnect', function (msg) {});
});

server.listen( 3000 , function() {
    console.log(" server is created ");
});



module.exports = app;
View Code

 

 

  客戶端的代碼你要引用socket.io模塊下的socket.io/socket.io.js, 你經過 new WebSocket("ws://127.0.0.1") 一直會提示錯誤, 錯誤消息以下:

WebSocket connection to 'ws://127.0.0.1/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

 

  而後經過socket.io這個庫給咱們提供的方法進行鏈接(我也不知道爲何這個能夠鏈接,使用new WebSocket反正是鏈接不了):

var ws = io.connect('http://localhost:3000');

 

  客戶端的代碼以下:

var ws = null;
var name = "";

var Ws = function(url) {
    /*
    只能說呵呵了, 使用new WebSocket沒法鏈接到服務器, 提示握手前斷開鏈接;
    if(!window.WebSocket)
        return null;
    var ws = new WebSocket( 'ws:' + window.location.href.substring(window.location.protocol.length) );
    */
    var ws = io.connect('http://localhost:3000');
    ws.on('open',function(data) {
        log(data);
        ws.send({});
    });

    ws.on("refreshUser", function(msg){
        $("<div></div>").html( msg+"登錄了哇" ).appendTo( $("#users") );
    });

    // socketIo鏈接開始握手的消息在chrome開發工具的請求中能夠看到,
    // 握手之後的消息傳送沒法截取;
    ws.on("message", function(data) {
        $("#output").html(" ");
        name = data.name;
        $("#name").val(data.name);
        var arr = data.msg;
        while( s = arr.shift() ) {
            log( s );
        };
        window.scrollTo(0, 100000);
    });

    var sendMessage = function(msg){
        ws.send(msg);
    };

    return ws;

    function log(s,e) {
        var output = document.getElementById("output");
        var p = document.createElement("p");
        p.style.wordWrap = "break-word";
        p.style.padding="10px";
        p.style.background="#eee";
        p.innerHTML = s.name + " at " + (new Date(s.time)).toDateString() + " :<br>==>> <b>"+ s.msg +"</b>";
        output.appendChild(p);
    };
};
function init() {
    ws = Ws();
    if(ws === null) {
        alert("不支持webSocket!");
    };

    $("#ipt").keydown(function(e) {
        var e = e || window.event;
        if (e.keyCode === 13) {
            var msg = $(this).val();
            if (!msg) return;
            ws.send({
                type : "add",
                msg : msg,
                name : $("#name").val()
            });
            $(this).val('');
        };
    });
};

window.onload = init;

 

 

  jade這個模板和express的路由什麼的就不說了, 本身寫個兩行就懂了, 教程那麼多, imooc屌炸天是否是哇, 明天覆習JAVASCRIPT搞基程序設計3, 你懂的;

  

  捐給給錢,這個個人支付寶帳號:mayun.taobao.com;

相關文章
相關標籤/搜索