socket.io在egg+vue中的使用

首先说明一下什么是socket.io,它和websocketAjax的区别在哪里。这里就不讲理论和运行机制了(我怕误人子弟…),只说一下我的理解。(socket.io/socketIO/socket有时候称呼的很乱,我不太清楚有没有具体的区别和特殊的含义,我习惯叫socket.io

  1. socket.iowebsocketwebsocket是一种客户端和服务器之间双向实时通信技术,是HTML5的新协议规范。websocket在建立握手连接时,数据是通过HTTP协议传输的,但是在TCP连接建立后,真正的数据传输阶段则不需要HTTP协议的参与。它讲究是随时随地的双向通信,应用场景包括客户端需要展示动态数据等。socket.io则是为了兼容不同的浏览器,在websocket上面封装了一层。
  2. socket.ioAjaxAjax是单向的,即客户端通过HTTP协议和服务器单向通信,流程就是客户端发出请求,服务器做出相应。 socket.io是双向的随时随地的通信,只是用一次HTTP协议建立连接TCP连接后,就不在使用HTTP协议了。优点也很明显节省带宽(HTTP数据包头本身的字节量较大)和服务器资源。

其他的详细介绍网上有很多就不在说了,网上说的千奇百怪的我就不贴网址了。下面说一下socket.ioegg+vue项目中的具体使用。

egg服务器端中使用:

egg-socket.io的官方文档 个人觉得他说的已经很清楚了…我大概重述总结一下吧。1、安装开启插件。2、配置ws引擎和命名空间。3、以sticky模式启动。4、配置Nginx。5、写soceket.io的controller和相应的router文件。(它中间件项目还没用到,我就不提了,有兴趣可以去看文档)。这个过程中需要动五个文件外加nginx的配置文件。
0、安装:$ npm i egg-socket.io --save
1、plugin.js文件:开启egg-socket.io

exports.io = {
  enable: true,
  package: 'egg-socket.io',
};

2、config.default.js文件:配置ws引擎和命名空间。

 exports.io = {  
   namespace: {
     init: { wsEngine: 'uws' },  //默认是ws引擎
     '/': {
       connectionMiddleware: [],
       packetMiddleware: [],
     },
   },
 };

3、package.json文件:修改启动方式

{
 "scripts": {
   "dev": "egg-bin dev --sticky",
   "start": "egg-scripts start --sticky"
 }
}

4、nginx的配置按照文档配置就行了,就不写了。
5、router.js文件:配置路由。

module.exports = app => {
 const { router, controller } = app;
 app.io.of('/').route('request', app.io.controller.socketio.index);  // namespace'/'要和配置的一致,消息名称'request'要和vue中一致
}

6、io/controller/socketio.js文件:具体的业务代码

class SocketIOController extends Controller {
 async index() {
   const { ctx } = this;
   const message = ctx.args[0];   //接受第一个参数:消息参数判断执行哪个函数
   if (message === 'hello') {
     const { param } =  ctx.args[1]  // 接受第二个参数:真正需要的参数
     // ...中间是具体的业务代码
     ctx.socket.emit('sendData', 'this is a response');   //消息名称'sendData'要和vue中一致,返回给客户端
   }
 }
}
module.exports = SocketIOController;

vue客户端中使用:

0、安装:npm install vue-socket.io --save
1、main.js文件:引入vue-socket.io

// 引入 socketio,配置了环境变量NODE_ENV,区分开发环境用的,没用到的可忽略。
// 环境变量VUE_APP_DEV_SERVER是需要连接的服务器地址
import Vue from 'vue';
import VueSocketIO from 'vue-socket.io';
if (process.env.NODE_ENV === 'production') {
  Vue.use(VueSocketIO, window.location.origin);   
} else {
  Vue.use(VueSocketIO, process.env.VUE_APP_DEV_SERVER);
  // 等同于 Vue.use(VueSocketIO, socketio('http://xxx.xxx.xx.xxx'));
}

2、组件内使用

  mounted() {
     this.$options.sockets.sendData= (data) => {   // ’sendData‘是由上面egg中controller中的emit决定的
       console.log(data)   //  接受到的消息输出为'this is a response'
     };
     
     this.$socket.emit('request', 'hello', { param: 'this is a param' }); // 'request' 是由egg的router决定的,后面是传给egg.controller的具体参数
     
     if (!this.intervalData) {  // 每五秒emit一次
       this.intervalData = setInterval(() => {
         this.$socket.emit('request', 'hello', { param: 'this is a param' });
       }, 5000);
     }
 },
 
 beforeDestroy() {
   delete this.$options.sockets.sendData;
   if (this.intervalTime) {
     clearInterval(this.intervalTime);
     this.intervalTime = null;
   }
 },

这样说明一下可能还是不太清楚(我也是尽力表达了),可以对比下图理解:socket.io在egg+vue中的使用_第1张图片
另外补充一点:nginx的配置,及时配置好了本地开发时也会有cros问题,但代码部署到服务器上的时候却没有cros问题。是因为开发时本地页面访问云服务器,chrome 浏览器作了限制。我们项目的nginx配置中已经add_header了,但是socket.io 的 response 本身也有个 Access-Control-Allow-Origin 头,add_header 后变成两个,所以就出现问题了。解决办法:修改 chrome 启动参数,在桌面上另建一个快捷方式,目标加--disable-web-security --user-data-dir="C:\temp"参数,开发时使用这个快捷方式启动浏览器。

你可能感兴趣的:(协议)