MQTT(二) 实现聊天功能

架构

客户打算把聊天内容发送到php server
php server 接收消息并进行相关业务处理,然后publish到redis
node js 作为mqtt 的broker 订阅redis
MQTT(二) 实现聊天功能_第1张图片

broker 安装

aedes可以在任何流服务器上运行的准系统 MQTT 服务器

  • 建立一个文件夹,并在该文件夹内打开终端初始化项目
$ npm init  -y	
$ npm install aedes
  • 安装redis mqemitter
$ npm install mqemitter-redis --save

新建index.js文件

var http = require('http')
var websocket = require('websocket-stream')
require('events').EventEmitter.defaultMaxListeners = 0

var mq = require('mqemitter-redis')({
  port: '6379',
  host: '127.0.0.1',
  password: '123456',
  db: 2
})

var aedes = require('aedes')({
  concurrency: 666,
  mq: mq
})

// 身份验证
aedes.authenticate = function (client, username, password, callback) {
    callback(null, (username === 'user' && password.toString() === '123456'));
}

//禁止pub
aedes.authorizePublish = function(client, packet, callback) {
  callback(new Error('no publish'));
};

//sub消息
aedes.authorizeSubscribe = function (client, sub, callback) {
  if (sub.topic === 'aaaa') {
    return callback(new Error('wrong topic'))
  }
  if (sub.topic === 'bbb') {
    // overwrites subscription
    sub.topic = 'foo'
    sub.qos = 1
  }
  callback(null, sub)
}

var server = require('net').createServer(aedes.handle)

server.listen(7888, function () {
  console.log('===server listening on port===', 1883)
})

var httpServ = http.createServer()
websocket.createServer({server: httpServ, port: 1884}, aedes.handle)

我们根据mqemitter-redis 拼装redis publish数据结构
mqemitter-redis.js

function handler (sub, topic, payload) {
    var packet = msgpack.decode(payload)
    //console.log("packet:"+packet.id)
    if(that.redisCache.set("p:"+packet.id, 1, "EX", 10, "NX")){
      //console.log("packet:"+packet.id+":ok")
      that._emit(packet.msg)
    }
  }

根据以上代码我们可以得到

  1. 消息需要msgpack压缩
  2. 必须有id,msg 字段
  3. msg 数据结构参考mqtt-packet 的publish结构
{
  cmd: 'publish',
  messageId: 42,
  qos: 1,
  dup: false,
  topic: 'test',
  payload: new Buffer('test'),
  retain: false,
  properties: { // optional properties MQTT 5.0
      payloadFormatIndicator: true,
      messageExpiryInterval: 4321,
      topicAlias: 100,
      responseTopic: 'topic',
      correlationData: Buffer.from([1, 2, 3, 4]),
      userProperties: {
        'test': 'test'
      },
      subscriptionIdentifier: 120, // can be an Array in message from broker, if message included in few another subscriptions
      contentType: 'test'
   }
}

php server 代码
server.php

public function send($topic, $content){
        $message = [];
        $message['id'] = uuid();
        $message['msg'] = [];
        $message['msg']['cmd'] = 'publish';
        $message['msg']['retain'] = false;
        $message['msg']['qos'] = 2;
        $message['msg']['topic'] = $topic;
        $message['msg']['payload'] = $content;
        $message['msg']['messageId'] = uuid();
        //$message['msg']['properties'] = ['messageExpiryInterval':125]; //optional properties
        //发布消息
        (\Redis ())->publish($topic, msgpack_pack($message));
}

$this->send('test','我就测试下');

$this->send('bbb','我就测试下');

把server.php 改成接收api 传递消息
前段监听1884端口
到此整个用MQTT 实现聊天功能的架构就完成了

总结

  1. 官方对于aedes的文档不甚详尽,对于我这node 渣渣来说还是很费劲
  2. 官方文档有介绍用Redis实现集群,虽然MQTT本是为物联网设计,但就我们的业务而言也是够用

你可能感兴趣的:(mqtt,工具,php,node.js,mqtt)