zoukankan      html  css  js  c++  java
  • nodeJS+express+Jade写一个局域网聊天应用(node基础)

      为了复习一下nodeJS, 而且socketIO这东西听起来就好高端有木有, 而且有人写过了open, 也可以作为自己的参考有木有, 点击下载源代码

      express是4.x的版本, 跟以前的配置有些区别, 我才不管呢, 好用就好>﹏<;

      按照正常的流程通过 node install 安装项目依赖, 项目的依赖如下;

      "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就会为你自动新建一个项目;)

      先来看下高大上的服务端截图;

      

      

      酷炫的客户端截图:

      

      客户端的主要功能是发送消息, 如果用户不输入名字后台会分配一个名字给客户端;

      服务端的主要功能是处理用户发送的数据, 然后把数据保存到json,  同时再把当前的新数据推送到所有 , 有连接到当前socket服务器的客户端;

      简单的服务端流程如下:

    //获取对应的依赖
    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;

  • 相关阅读:
    万字攻略,详解腾讯面试
    百度广告产品系统级测试技术演进
    TAR部署MYSQL(1)
    RPM部署MYSQL
    大数据学习之Linux(3)
    大数据学习之linux(2)
    大数据学习之linux(1)
    pycharm安装与破解
    Dijkstra—校园景点游览问题
    哈夫曼编译码器
  • 原文地址:https://www.cnblogs.com/diligenceday/p/4230737.html
Copyright © 2011-2022 走看看