swoole implements multi-to-multi-group chat

Refer to the blog, you can see the original text, here just according to business needs to make changes.
Backend reference
swoole creates multi-person multi-room chat room 1
swoole Creates Multi-Person and Multi-Room Chat Room 2
swoole Creates Multi-Person and Multi-Room Chat Room 3
Front-end reference
Chat Room for Wechat Program Development

Setting up environment and domain name configuration, we skipped here first. You can Baidu by yourself.
Don't talk too much, just go to the code.

PHP code

<?php

define('HOST', '0.0.0.0');
define('PORT', '19501');
define('WORKER_NUM', 10);
define('DISPATCH_MODE', 2);
define('DAEMONIZE', 0);

class WebsocktDemo
{
    public $ws = null;
    public $redis = null;
    public function __construct()
    {

        $this->ws = new Swoole\WebSocket\Server(HOST, PORT);
        $this->redis = $this->redis();
        $this->redis->auth("***********");

        //$this->ws->on("start", [$this, 'onStart']);
        $this->ws->on("open", [$this, 'onOpen']);
        $this->ws->on('message',[$this,'onMessage']);
        $this->ws->on('close',[$this,'onClose']);
        $this->ws->start();
    }
	/**
     * Get a redis instance
     * @return null|Redis
     */
    protected function redis()
    {
        static $redis = null;
        if (is_null($redis)) {
            $redis = new \Redis();
            $redis->connect("*********");
        }

        return $redis;
    }
    
    /**
     * Monitor user link events, link with user id and room id parameters, and then save the user to the room domain
     */
    public function onOpen($server, $request){
        //Join the room area
        $this->redis->hset($request->get['room'], $request->get['uid'], $request->fd);
        //Join Group Collection
        $this->redis->sadd('group', $request->get['room']);
    }
    
    /**
     * Listen for callbacks to receive events
     */
    public function onMessage($server, $frame)
    {
        //Push when receiving data, and every time you send a message, you need to bring a label message (uid, room)
        $data = json_decode($frame->data, true);
        //Assembling Data Judgment Type
        switch ($data['type']){
            case "change"://send message
                $arr['name'] = $data['name'];
                $arr['content'] = $data['content'];
                $arr['type'] = "change";
                $arr['uid'] = $data['uid'];
                $arr['room'] = $data['room'];
                break;
        }
        //Push the message to the room.
        self::push_room($data['room'], $arr);
    }
    
	/**
     * Listen for callbacks to closure events. This step is copied without modification.
     */
    public function onClose($ser, $fd)
    {
        //Exit and delete redundant group fd
        $group = $this->redis->sMembers('group');
        foreach ($group as $v) {
            $fangjian = $this->redis->hgetall($v);
            foreach ($fangjian as $k => $vv) {
                if ($fd == $vv) {
                    $this->redis->hdel($v, $k);
                }
            }
        }
    }
  }
  //Finally instantiate the object
  new WebsocktDemo();
    

The back-end code mainly uses Swoole's WebSocket service and redis hash domain concepts. At the beginning, it did not think of using redis, but directly linked to data. Later, referring to other people's articles, it became clear and clear, and changed to redis (manual funny), and by the way, learned about redis'hsah.

Widget websocket.js code

// Request domain name
var url = 'wss://Your wss domain name';
// Room information
var room = ''
// User Signature
var sign = 0
// User name
var name = null;
// Received message callback function
var func = null;

function connect(room,sign,name,func) {
  //The goal of globalizing link information is to re-link after disconnection,* if the front end does not interact with socket for more than a minute, it will automatically disconnect.
  let that = this
  room = room
  sign = sign
  name = name
  func = func
  wx.connectSocket({
    url: url + "?room="+room+"&uid="+sign+"&name="+name,
    method: 'post',
    header:{'content-type': 'application/json'},
    success: function (res) {
      console.log('Successful connection',res)
    },
    fail: function (res) {
      console.log('connection failed',res)
      wx.closeSocket()
    }
  })
  wx.onSocketOpen(function (res) {
     //Accept server messages
     wx.onSocketMessage(func);//func callback can get the data returned by the server
  });
  wx.onSocketClose(function (res) {
    console.log("link failure",res);
    if(res.reason == "abnormal closure" && res.code == 1006){//Realize reconnection
      that.connect(room,sign,name,func);
    }
  });
}
//send message
function send(msg,callbackll) {
  wx.sendSocketMessage({
    data: msg,
    complete(res){
      callbackll(res);
    }
  });
}
module.exports = {
  connect: connect,
  send: send
}

Applet js code

import websocket from "../utils/websocket.js";
//When the page is loaded, it links to the soket and listens for the server to return the message.
onLoad: function (options) {
	websocket.connect(options.id, wx.getStorageSync("sign"), nickname, function (res) {
		//Listen for data callback time
		let server = JSON.parse(res.data)
		that.setData({
			bullet_screen: that.data.bullet_screen.concat(server)
		})
	})
}
// Send to socket
send: function (e) {
  let that = this
  if (that.data.msgContent == '') {
    wx.showToast({
      title: 'Please enter what you want to say.',
      icon: 'none',
      duration: 2000
    })
    return false
  }
  websocket.send('{"name":"' + wx.getStorageSync("nickname") + '","uid":"' + wx.getStorageSync("sign") + '","type":"change","room": "' + that.data.roomid + '","content": "' + that.data.msgContent + '"}', function (call) {
    if (call.errMsg == "sendSocketMessage:fail WebSocket is not connected") {
      wx.showToast({
        title: 'fail in send',
        icon: "none",
        duration: 2000
      })
      return false;
    }
    that.setData({
      msgContent: ''
    })
  })
}

The front end mainly uses the websocket link API of the Wechat applet, which can encapsulate the whole websocket into a tool class.
js only has two core codes, one is the processing of the return message after the front-end link socket, and the second is sending the message to socket. There are only so many core parts of the whole front-end and back-end code, which are much the same as other blogs, mainly depending on your business needs and different ways of implementation.
Front-end html is not shown here, mainly the array returned by the circular server, and then add css style according to different type values, you can achieve some special style requirements.

Tags: Redis socket PHP JSON

Posted on Thu, 29 Aug 2019 04:02:01 -0700 by tmharrison