nodejs 10 nodejs的web应用-文字直播实例

  • 功能分析

    1. 用户: 直播员(登录), 游客。
    2. 直播方式:直播员登录后台,输入相应的的直播信息(图片和文字)。
    3. 技术统计: 在线实时记录运动员数据。
    4. 游客套路: 游客实时进行在线讨论。
    5. 微博分享: 游客通过腾讯微博和新浪微博分享直播内容。

  • 模块示意图

    image

    1. 5个controller对应5个模块chat.js, live.js,login.js, score.js, share.js
    2. 5个controller继承父类action.js
    3. router.js负责路由处理
    4. app.js入口文件, 初始化路径以及项目所需模块

  • 分析所用到的模块

    Node.js模块名文件名称模块描述
    httpNode.js原生模块负责服务器创建管理
    fsNode.js原生模块文件处理,读取
    urlNode.js原生模块url请求路径处理
    querystringNode.js原生模块HTTP请求参数分析模块
    httpParamhttp_param.js负责HTTP参数GET和POST获取方式
    staticModulestatic_module.js负责本系统所有静态文件的管理
    routerrouter.js本系统路由处理模块
    actionaction.js系统controller基类
    jadeNPM模块前端模板
    socketNPM模块socket模块
    pathNode.js原生模块路径处理
    utilNode.js原生模块主要应用其继承API
    sessionnode_session.js他人开发的一个sessiong管理模块

  • 目录结构

    ├── app // Node.js可运行代码
    │ ├── controller // controller层
    │ ├── core //无依赖的模块
    ├── conf // 配置文件信息
    ├── node_modules //依赖
    ├── static //静态文件资源
    │ ├── css
    │ ├── images
    │ ├── js
    ├── view //jade模块文件
    ├── app.js //启动文件


主要模块介绍

  1. app.js

    • 文件路径统一化管理
    • 文件路径名使用全大写字母进行变量命名
    • 所有应用到的模块添加命名空间,统一管理
    • 响应类方法或数据,同意添加到相应对象res中进行管理
    /**
     * 设置路径全局变量
     */
    global.BASE_DIR = __dirname;
    global.APP = BASE_DIR + "/app/";
    global.CON = APP + "/controller/";
    global.CORE = APP + "/core/";
    global.LIB = BASE_DIR + "/self_modules/";
    global.CONF = BASE_DIR + "/conf/";
    global.STATIC = BASE_DIR + "/static/";
    global.VIEW = BASE_DIR + "/view/";
    
    /**
     * modules 引入
     */
    global.lib = {
      http : require("http"),
      fs: require("fs"),
      url: require("url"),
      querystring: require("querystring"),
      httpParam: require(LIB + "http_param"),
      router: require(CORE + "router"),
      action: require(CORE + "action"),
      jade: require("jade"),
      socket: require("socket.io"),
      path: require("path"),
      parseCookie: require("connect").utils.parseCookie,
      session: require(LIN + "node_session"),
      util: require("util")
    }
    
    
    global.onlineList = []; //存储socket链接用户信息
    
    global.app = lib.http.createServer(function(req, res){
      //jade
      res.render = function(template, options){
            var str = fs.readFileSync(template, 'utf8');
            var fn = jade.compile(str, { filename: template, pretty: true });
            var page = fn(options);
            res.writeHead(200, { 'Content-Type': 'text/html' });
            res.end(page);
        }
        lib.router.router(req, res); //调用router的router方法执行url路由处理
    }).listen(3000);
    console.log('Server running at http://127.0.0.1:3000/');
    
    global.io = lib.socket.listen(app);
    
  2. router.js

    • 对url请求处理, 同时分发到相应的controller进行逻辑处理响应HTTP信息
    var Login = require(Con + "login"); //登录模块
    exports.router = function(req, res) {
      var pathname = decodeURI(lib.url.parse(req.url).pathname); //解析编码后的url
      lib.pathname.init(req, res); //初始化HTTP的GET和POST获取参数
      global.sessionLib = lib.session.start(res, req);  //session start
      var model = pathname.substr(1), //获取请求的controoler
      controller = lib.httpParam.GET("c"), //获取请求的controoler中的函数方法
      Class = "";
    
      if(pathname == '/favicon.ico') {
        return;
      } else if(pathname == '/') {
        res.render (VIEW + 'index.jade');
        return;
      }
    
      try {
        Class = require(CON + model); //require一个请求的类
      } catch (e) { //失败时,默认为请求静态文件
        lib.staticModule.getStaticFile(pathname, req, res, BASE_DIR);
        return;
      }
    
      if(Class) {
        var login = new Login(req, res);
        var ret = login.checkSssion(model); //判断用户是否已登录
        if(ret) {
          var object = new Class(req, res); //创建请求controller类的对象object
          object[controller].call(); //调用object对象的controller方法
        } else {
          res.render(VIEW + "index.jade"); //未登录跳转到index.jade
        }
      } else {
        res.writeHead(404, {"Content-Type": "plain/text"});
        res.end("can not find source");
      }
    }
    
  3. Login类

    • 分管理员登录和游客登录,跳转live.jade 和main.jade
    • 登录作session处理
    • socket连接, 文字直播
    module.exports = function() {
      var _req = arguments[0];
      var _res = arguments[1];
    
      /**
       * 判断用户是否已登录
       * @param {string} model 访问模块 'login'时不需要去验证session
       * @returns bool true登录|false未登录
       */
      this.checkSession = function(model) {
        if(model == 'login') {
          return true;
        }else if (sessionLib.username && sessionLib.username != '') {
          return true;
        }
        return false;
      }
    
      this.login = function() {
        //调用HTTP POS参数获取方法
        lib.httpParam.POST('username', function(value) {
          sessionLib.username = value; //设定Session中username值
          if(value == 'zula') { //管理员登录直接进入直播模块
            _res.render(VIEW + 'live.jade', {'user': value});
          } else { //进入观看直播模块
            _res.render(VIEW + 'main.jade', {'user': value});
          }
          //socket监听
          var time = 0;
          io.sockets.on("connection", function(socket) {
            var username = sessionLib.username;
    
            if(!onlineList[username]) {
              onlineList[username] = socket;
            }
    
            //设置刷新在线用户数函数
            var refresh_online = function() {
              var n = [];
              for (var i in onlineList) {
                n.push(i);
              }
              var message = lib.fs.readFileSync(BASE_DIR + '/live_data.txt', 'utf8');
              socket.emit('live_data', message);
              //如果有用户登录或退出, 广播在线用户列表。
              io.sockets.emit("online_list", n); //所有人广播
            }
            refresh_online();
            //确保每次发送一个socket消息
            if(time > 0) {
              return;
            } 
    
            socket.on("public", function(data) {
              var insertMsg = "<li><span class='icon-user'></span>";
              insertMsg += "<span class='live_user_name text-success'>[zula]</span>";
              insertMsg += "<span class='live_message text-info'>" + data.msg + "</span></li>";
    
              writeFile( {'msg': insertMsg, 'data': data}, function(data) {
                io.sockets.emit('msg', data);
              } )
            });
    
            socket.on("disconnect", function() {
              delete onlineList[username];
              refresh_online();
            });
            time ++;
          })
        });
      }
    }
    
    
    function writeFile(data, callback) {
      var message = lib.fs.readFileSync(BASE_DIR + '/live_data.txt', 'utf8');
      lib.fs.writeFile(BASE_DIR + '/live_data.txt', message + data.msg, function(err) {
        if (err) throw err;
        callback(data.data);
      })
    }
  4. 代码仓库(喜欢请star(๑•ᴗ•๑))

  5. 未完待续。。。略粗糙, 继续加功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值