什么是Socket.io
一个基于 Node.js 的实时应用程序框架,在即时通讯、通知与消息推送,实时分析等场景中有较为广泛的应用
什么是egg-socket.io
- 对socket.io的二次封装, 增加了一些开发规范
- 增加namespace(命名空间), 可以通过配置的方式定义
- 增加middleware, 对每一次socket连接的建立、断开、消息和数据传递进行预处理
- controller, 相应socket.io的event事件
- router, 同一了socket.io的event与框架路由的处理配置方式
把egg-socket.io整合到我们的egg项目中
- 安装egg-socket.io
npm i egg-socket.io --save
- 开启插件
// {app_root}/config/plugin.js
exports.io = {
enable: true,
package: 'egg-socket.io',
};
- 配置egg-socket.io
// {app_root}/config/config.${env}.js
exports.io = {
init: {}, // passed to engine.io
// namespace命名空间配置为/
namespace: {
'/': {
// 预处理器中间件, 我们这里配置了一个auth, 进行权限判断, 它对应的文件是/app/io/middleware/auth.js, 这里可以配置多个文件, 用逗号隔开
connectionMiddleware: ['connection'], //这里我们可以做一些权限校验之类的操作
packetMiddleware: [] //通常用于对消息做预处理,又或者是对加密消息的解密等操作
}
},
// 配置redis, 非必须, 不需要的可以不配置这块, egg-socket.io内置了socket-io-redis, 在cluster模式下, 使用redis可以较为简单的实现clients/rooms等信息共享
redis: {
host: '127.0.0.1',
prot: 6379,
auth_pass: 123456,
db: 0
}
};
到这里egg-socket.io已经开启并配置完毕了, 接下来我们就要编写路由和控制器了
- 先来看下egg-socket.io的项目目录结构
your-project-name
├── app
│ ├── extend
│ │ └── helper.js
│ ├── io
│ │ ├── controller
│ │ │ └── chat.js
│ │ └── middleware #插件中间件, 基于 socket 模型设计,处理 socket.io 请求
│ │ ├── auth.js #对应刚才配置的connectionMiddleware: ['auth']
│ └── router.js
├── config
└── package.json
- 先配置路由
// /app/router.js
module.exports = app => {
const { router, controller, io } = app;
// http 接口, 在对应的控制器中可以直接操作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);
};
- 然后创建auth.js
// app/io/middleware/auth.js
module.exports = app => {
return async (ctx, next) => {
console.log('接收客户端发来的传参数据', ctx.query);
ctx.socket.emit('room', '客户端链接上了!');
await next();
console.log('断开链接了!');
};
};
- 最后创建聊天控制器
// /app/io/controller/chat.js
'use strict';
const Controller = require('egg').Controller;
class ChatController extends Controller {
async index() {
const { ctx, app } = this;
const message = ctx.args[0];
// console.log('ctx.args', ctx.args);
console.log('chat 控制器打印', message);
await ctx.socket.emit('room', `Hi!${ctx.socket.id} 我是服务端,我接收到了你的消息: ${message}`);
}
}
module.exports = ChatController;
- 我们可以在常规的http-controller中给客户发送消息
// app/controller/home.js
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const {app, query} = this.ctx;
// 给谁发, socket连接的id
const id = query.id;
const nsp = app.io.of('/');
if(nsp.sockets[id]){
// 通过id给指定socket连接发送消息
nsp.sockets[id].emit('res', 'hello http....');
}
// 给整个房间发送消息
nsp.server.sockets.emit('room', '我要爬虫了');
// https接口返回
this.ctx.body = "发送成功";
}
}
module.exports = HomeController;
到这里服务端完成, 下面我们来写一个简单的socket.io客户端
<script src="https://cdn.bootcss.com/socket.io/2.1.0/socket.io.js"></script>
<script>
// 客户端
const log = console.log;
window.onload = function () {
// init
const socket = io('/', {
// 实际使用中可以在这里传递参数
query: {
room: 'demo',
userId: `client_${Math.random()}`
},
transports: ['websocket']
});
socket.on('connect', () => {
const id = socket.id;
log('#connect,', id, socket);
// 给服务端发消息
socket.emit('chat', 'hello world!', '给客户端发消息');
// 监听自身 id 以实现 p2p 通讯
socket.on(id, msg => {
log('#监听客户端发给自己消息,', msg);
});
});
// 监听某个房间的消息
socket.on('room', msg => {
log('#接收某个房间的消息,', msg);
});
// 接收在线用户信息
socket.on('online', msg => {
log('#online,', msg);
});
// 系统事件
socket.on('disconnect', msg => {
log('#disconnect', msg);
});
socket.on('disconnecting', () => {
log('#disconnecting');
});
socket.on('error', () => {
log('#error');
});
window.socket = socket;
};
</script>
宝塔服务器里能够通过创建一个静态站,然后配置ngnix反向代理来配置node服务器
当然也可以直接创建一个node项目,反向代理自动被创建了
如果是宝塔服务器之自己创建反向代理的时候,项目中有socket传输,记得在反向代理配置文件里加上这段话
location /socket.io {
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:5001;
}
相关推荐:
Socket.IO - Egghttps://www.eggjs.org/zh-CN/tutorials/socketio#%E5%AE%89%E8%A3%85-egg-socketio