• egg-socket 配置和使用


    nodejs

    Socket.IO

    Socket.IO 是一个基于 Node.js 的实时应用程序框架,在即时通讯、通知与消息推送,实时分析等场景中有较为广泛的应用。

    WebSocket 的产生源于 Web 开发中日益增长的实时通信需求,对比基于 http 的轮询方式,它大大节省了网络带宽,同时也降低了服务器的性能消耗;socket.io 支持 websocket、polling 两种数据传输方式以兼容浏览器不支持 WebSocket 场景下的通信需求。

    框架提供了 egg-socket.io插件,增加了以下开发规约:

    • namespace: 通过配置的方式定义 namespace(命名空间)
    • middleware: 对每一次 socket 连接的建立/断开、每一次消息/数据传递进行预处理
    • controller: 响应 socket.io 的 event 事件
    • router: 统一了 socket.io 的 event 与 框架路由的处理配置方式

    安装 

    $ npm i egg-socket.io --save

    开启插件

    // {app_root}/config/plugin.js
    exports.io = {
      enable: true,
      package: 'egg-socket.io',
    }; 

    配置

    // {app_root}/config/config.${env}.js
    exports.io = {
      init: { }, // passed to engine.io
      namespace: {
        '/': {
          connectionMiddleware: [],
          packetMiddleware: [],   // 针对消息的处理暂时不实现
        },
      },
    };

    开启 egg-socket.io 的项目目录结构

    chat
    ├── app
    │   ├── extend
    │   │   └── helper.js
    │   ├── io
    │   │   ├── controller
    │   │   │   └── default.js
    │   │   └── middleware
    │   │       ├── connection.js
    │   │       └── packet.js
    │   └── router.js
    ├── config
    └── package.json

    注意:对应的文件都在 app/io 目录下

    Router 配置 (路由负责将 socket 连接的不同 events 分发到对应的 controller),不用controller方法可以暂时不用配置

    // {app_root}/app/router.js
    
    module.exports = app => {
      const { router, controller, io } = app;
    
      // default
      router.get('/', controller.home.index);
    
      // socket.io
      io.of('/').route('server', io.controller.home.server);
    };

     egg-socket.io中间件负责 socket 连接的处理

    // {app_root}/app/io/middleware/auth.js
    
    const PREFIX = 'room';   //定义房间号
    
    module.exports = () => {
      return async (ctx, next) => {
        const { app, socket, logger, helper } = ctx;
        const id = socket.id;
        const nsp = app.io.of('/');
        const query = socket.handshake.query;  //获取socket链接传过来的参数
    
        // 用户信息
        const { room, userId } = query;
        const rooms = [ room ];
    
        logger.debug('#user_info', id, room, userId);
    
        const tick = (id, msg) => {
          logger.debug('#tick', id, msg);
    
          // 踢出用户前发送消息
          socket.emit(id, helper.parseMsg('deny', msg));
    
          // 调用 adapter 方法踢出用户,客户端触发 disconnect 事件
          nsp.adapter.remoteDisconnect(id, true, err => {
            logger.error(err);
          });
        };
    
        // 检查房间是否存在,不存在则踢出用户
        // 备注:此处 app.redis 与插件无关,可用其他存储代替
        const hasRoom = await app.redis.get(`${PREFIX}:${room}`);
    
        logger.debug('#has_exist', hasRoom);
    
        if (!hasRoom) {
          tick(id, {
            type: 'deleted',
            message: 'deleted, room has been deleted.',
          });
          return;
        }
    
        // 用户加入
        logger.debug('#join', room);
        socket.join(room);
    
        // 在线列表
        nsp.adapter.clients(rooms, (err, clients) => {
          logger.debug('#online_join', clients);
    
          // 更新在线用户列表
          nsp.to(room).emit('online', {
            clients,
            action: 'join',
            target: 'participator',
            message: `User(${id}) joined.`,
          });
        });
    
        await next();
    
        // 用户离开
        logger.debug('#leave', room);
    
        // 在线列表
        nsp.adapter.clients(rooms, (err, clients) => {
          logger.debug('#online_leave', clients);
    
          // 获取 client 信息
          // const clientsDetail = {};
          // clients.forEach(client => {
          //   const _client = app.io.sockets.sockets[client];
          //   const _query = _client.handshake.query;
          //   clientsDetail[client] = _query;
          // });
    
          // 更新在线用户列表
          nsp.to(room).emit('online', {
            clients,
            action: 'leave',
            target: 'participator',
            message: `User(${id}) leaved.`,
          });
        });
    
      };
    };

     Controller 对客户端发送的 event 进行处理;

    // {app_root}/app/io/controller /nsp.js
    'use strict';
    
    const Controller = require('egg').Controller;
    
    class NspController extends Controller {
    
    }
    
    module.exports = NspController;

     使用方法

    async index(){
    const nsp = this.app.io.of('/');
    nsp.to('app1').emit("step",{数据});
    }

    vue

    安装 sockrt.io 和 调用

    $ npm i socket.io-client –save
    import io from 'socket.io-client'; 

    vue.config.js配置

    '/socket.io': {

      target: 'http://127.0.0.1:7001',
    
  changeOrigin: true,

      ws:true,
    
  pathRewrite: {
 
       '^/socket.io': '/socket.io'

      }

    }

    使用方法

    //createIdSocket方法在mounted里面调用就可以
    createIdSocket(){
    
  const socket = io.connect(location.origin, {
    
    transports: ['websocket'],  //传输方式为'websocket'
        query: {

          sessionId: 'app1'
    //app1为房间号
       }
    
  });

      socket.on("connect", () => {
 
      });

      socket.on("step", msg => {
    
    console.log('msg',msg); //返回数据的处理
    
  });
      //重新连接时,将transports选项重置为Websocket  
      socket.on('reconnect_attempt', () => {

        socket.io.opts.transports = ['polling', 'websocket'];

      });
}

     注:socket 数据通信通过房间号建立联系确定获取数据内容

  • 相关阅读:
    vimrc 配置 史上最牛
    nmap 黑客 端口扫描(转)
    linux export 命令(转)
    【引用】linux下编译静态库ranlib有什么用
    vim map nmap(转)
    vim 自定义命令 自定义快捷键(转)
    vimrc初学 vim 快捷键 map(转)
    vim 取消 查找 高亮
    Java内存模型(JMM)学习总结
    Struts2和Spring整合
  • 原文地址:https://www.cnblogs.com/Li--gm/p/13468110.html
Copyright © 2020-2023  润新知