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

来源:互联网 发布:陈浩筹码分布源码公式 编辑:程序博客网 时间:2024/06/05 05:50
  • 功能分析

    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模块名 文件名称 模块描述 http Node.js原生模块 负责服务器创建管理 fs Node.js原生模块 文件处理,读取 url Node.js原生模块 url请求路径处理 querystring Node.js原生模块 HTTP请求参数分析模块 httpParam http_param.js 负责HTTP参数GET和POST获取方式 staticModule static_module.js 负责本系统所有静态文件的管理 router router.js 本系统路由处理模块 action action.js 系统controller基类 jade NPM模块 前端模板 socket NPM模块 socket模块 path Node.js原生模块 路径处理 util Node.js原生模块 主要应用其继承API session node_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. 未完待续。。。略粗糙, 继续加功能