egg.js整合通訊

##### 什么是Socket.io

一個(gè)基于 Node.js 的實(shí)時(shí)應(yīng)用程序框架,在即時(shí)通訊、通知與消息推送,實(shí)時(shí)分析等場(chǎng)景中有較為廣泛的應(yīng)用

##### 什么是egg-socket.io

- 對(duì)socket.io的二次封裝, 增加了一些開(kāi)發(fā)規(guī)范

- 增加namespace(命名空間), 可以通過(guò)配置的方式定義

- 增加middleware, 對(duì)每一次socket連接的建立、斷開(kāi)、消息和數(shù)據(jù)傳遞進(jìn)行預(yù)處理

- controller, 相應(yīng)socket.io的event事件

- router, 同一了socket.io的event與框架路由的處理配置方式

##### 把egg-socket.io整合到我們的egg項(xiàng)目中

不知道怎么搭建egg項(xiàng)目的翻下以前的文章

- 安裝egg-socket.io

```

cnpm i egg-socket.io -S

```

- 開(kāi)啟插件

{app_root}/config/plugin.js

```

exports.io = {

? enable: true,

? package: 'egg-socket.io',

};

```

- 配置egg-socket.io

{app_root}/config/config.default.js

```

module.exports = appInfo => {

? const config = exports = {

? ? io: {

? ? ? # namespace命名空間配置為/

? ? ? namespace: {

? ? ? ? '/': {

? ? ? ? ? # 預(yù)處理器中間件, 我們這里配置了一個(gè)auth, 進(jìn)行權(quán)限判斷, 它對(duì)應(yīng)的文件是/app/io/middleware/auth.js, 這里可以配置多個(gè)文件, 用逗號(hào)隔開(kāi)

? ? ? ? ? connectionMiddleware: ['auth'], #這里我們可以做一些權(quán)限校驗(yàn)之類的操作

? ? ? ? ? packetMiddleware: [], # 通常用于對(duì)消息做預(yù)處理,又或者是對(duì)加密消息的解密等操作

? ? ? ? },

? ? ? },

? ? ? # 配置redis, 非必須, 不需要的可以不配置這塊, egg-socket.io內(nèi)置了socket-io-redis, 在cluster模式下, 使用redis可以較為簡(jiǎn)單的實(shí)現(xiàn)clients/rooms等信息共享

? ? ? redis: {

? ? ? ? host: 'ip地址',

? ? ? ? prot: 6379,

? ? ? ? auth_pass: 123456,

? ? ? ? db:0,

? ? ? }

? ? }

? };

? 省略 .....

};

```

到這里egg-socket.io已經(jīng)開(kāi)啟并配置完畢了, 接下來(lái)我們就要編寫路由和控制器了

- 先來(lái)看下egg-socket.io的項(xiàng)目目錄結(jié)構(gòu)

```

your-project-name

├── app

│? ├── extend

│? │? └── helper.js

│? ├── io

│? │? ├── controller

│? │? │? └── chat.js

│? │? └── middleware #插件中間件, 基于 socket 模型設(shè)計(jì),處理 socket.io 請(qǐng)求

│? │? ? ? ├── auth.js #對(duì)應(yīng)剛才配置的connectionMiddleware: ['auth']

│? └── router.js

├── config

└── package.json

```

- 先配置路由

/app/router.js

```

module.exports = app => {

? const { router, controller, io } = app;

? //http 接口, 在對(duì)應(yīng)的控制器中可以直接操作socket, 非常方便

? router.get('/', controller.home.index);

? router.get('/user', controller.user.index);

?

? // socket, 指向app/io/controller/chat.js的index方法

? io.route('chat', app.io.controller.chat.index);

};

```

- 然后創(chuàng)建auth.js

app/io/middleware/auth.js

```

const room = "default_room";

module.exports = () => {

? ? return async(ctx, next) => {

? ? ? ? // 權(quán)限校驗(yàn)通過(guò)

? ? ? ? ctx.socket.emit('res', 'auth success');

? ? ? ? // 加入房間

? ? ? ? socket.join(room);

? ? ? ? // 放行

? ? ? ? await next();

? ? ? ? console.log('斷開(kāi)連接');

? }

};

```

- 最后創(chuàng)建聊天控制器

app/io/controller/chat.js

```

'use strict';

const Controller = require('egg').Controller;

const room = 'default_room';

class ChatController extends Controller {

? ? async index(){

? ? ? ? const {app, socket, logger, helper} = this.ctx;

? ? ? ? const id = socket.id;

? ? ? ? // 根據(jù)id給指定連接發(fā)送消息

? ? ? ? nsp.sockets[id].emit('res', "hello ....");

? ? ? ? // 指定房間連接信息列表

? ? ? ? nsp.adapter.clients([room], (err, clients) => {

? ? ? ? ? ? console.log(JSON.stringify(clients));

? ? ? ? });

? ? ? ? //? 給指定房間的每個(gè)人發(fā)送消息

? ? ? ? this.ctx.app.io.of('/').to(room).emit('online', this.ctx.socket.id+ "上線了");

? ? ? ? // 斷開(kāi)連接

? ? ? ? this.ctx.socket.disconnect();

? ? }

}

module.exports = ChatController;

```

- 通過(guò)調(diào)用http接口給客戶端發(fā)送消息

說(shuō)白了就是在http接口的控制器中發(fā)送socket消息

app/controller/home.js

```

const Controller = require('egg').Controller;

class HomeController extends Controller {

? async index() {

? ? const {app, query} = this.ctx;

? ? // 給誰(shuí)發(fā), socket連接的id

? ? const id = query.id;

? ? const nsp = app.io.of('/');

? ? if(nsp.sockets[id]){

? ? // 通過(guò)id給指定socket連接發(fā)送消息

? ? ? nsp.sockets[id].emit('res', 'hello http....');

? ? }

? ? this.ctx.body = "發(fā)送成功";

? }

}

module.exports = HomeController;

```

到這里服務(wù)端完成, 下面我們來(lái)寫一個(gè)簡(jiǎn)單的socket.io客戶端

```

const socket = require('socket.io-client')('http://127.0.0.1:7001');

// 連接服務(wù)端

socket.on('connect', () => {

? console.log('connect!');

? socket.emit('chat', 'hello world!');

});

//接收消息通知

socket.on('res', msg => {

? console.log('res from server: %s!', msg);

});

// 接收上線通知

socket.on('online', msg=>{

? console.log('online from server: %s!', msg);

});

```

到這就結(jié)束了, 有問(wèn)題留言!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ##### 什么是Socket.io 一個(gè)基于 Node.js 的實(shí)時(shí)應(yīng)用程序框架,在即時(shí)通訊、通知與消息推送,實(shí)...
    49a054febed1閱讀 5,204評(píng)論 5 2
  • 1.編碼規(guī)范 1.1 編碼格式與語(yǔ)法 項(xiàng)目默認(rèn)編碼格式統(tǒng)一為UTF-8格式,語(yǔ)法采用ES6+語(yǔ)法 1.2 代碼注釋...
    ZZES_ZCDC閱讀 4,773評(píng)論 6 19
  • 個(gè)人入門學(xué)習(xí)用筆記、不過(guò)多作為參考依據(jù)。如有錯(cuò)誤歡迎斧正 目錄 簡(jiǎn)書好像不支持錨點(diǎn)、復(fù)制搜索(反正也是寫給我自己看...
    kirito_song閱讀 2,651評(píng)論 1 37
  • 1、websocket websocket是html5出的協(xié)議,它是基于TCP協(xié)議,利用http協(xié)議建立連接,實(shí)現(xiàn)...
    微塵_7bd8閱讀 5,053評(píng)論 0 1
  • Egg上手 框架內(nèi)置基礎(chǔ)對(duì)象 框架內(nèi)置基礎(chǔ)對(duì)象 this*this對(duì)象比較特殊,分析應(yīng)為每次請(qǐng)求時(shí)和ctx一起實(shí)例...
    Silver湫澲閱讀 840評(píng)論 0 0

友情鏈接更多精彩內(nèi)容