Implementation of chat room with tp5.1.18 + spool

Time:2021-1-26

Implementation of chat room with tp5.1.18 + spool


TP is the latest version;
About the realization of the user registration, after registration, jump to the login page;
After login, the identity token is generated and stored in redis;
There is no Ajax request in the chat interface. As long as there is an HTTP request when shaking hands, I really can’t understand some people who publish messages in the chat interface with Ajax,

After some processing, only one account can be used in one browser, so two browsers must be used in the test

Then jump to the chat interface, and then establish websocket handshake, and carry toekn and the other party’s ID (friend’s ID) at the same time;

The background server does a series of operations when onopen, such as (detecting token, detecting friend’s ID, updating its ID and FD to data table, FD binding uid, etc.);
After these tests are passed, the chat records are obtained. For efficiency, 15 chat records with friends are pulled;

Get the data sent in onmessage!
After sending, check whether the other party is online. If not, don’t send it to the other party. If the other party is online, push the information to him!

Heartbeat detection: once every 5 seconds, if there is no operation in 100 seconds, the connection will be disconnected, and the FD in the database will be cleared at the same time!

The code is very simple, but there are some problems that have not been solved, such as online statistics

The socket is pasted below_ Server.php The rest of the code is no logical code!

Complete and so on after writing out again, everybody makes progress together!

<?php
/**
 *User: Li Haotian
 * Date: 18/7/03
 *Time: 4:19 am
 * Email: [email protected]
 */

namespace app\index\controller;

use app\index\model\Message;
use app\index\model\User as UserModel;
use app\tool\Tool;
use think\facade\Cache;
use swoole_websocket_server;

class Swoole extends \think\swoole\Server
{
    protected static $token;
    protected $host = '127.0.0.1';
    protected $port = 9508;
    protected $serverType = 'socket';
    protected static $uid = '';
    protected $option = [
        'worker_ Num '= > 4, // set the number of worker processes started 
        'daemonize '= > false, // daemonize.
        'backlog' = > 128, // listen queue length,
        'dispatch_mode' => 2,
        'heartbeat_check_interval' => 5,
        'heartbeat_idle_time' => 100,
    ];


    public function onOpen(swoole_websocket_server $server, \swoole_http_request $req)
    {
        $fd = $req->fd;
        $token = $req - > get ['token ']?'; // get the client user ID
        if (!$token) {
            $server - > push ($FD, tool:: showajax (['status' = > 3, 'message' = >'Please log in first!]));
            $server->close($fd);
            return;
        }

        $userData = Cache::get($token);
        if (!$userData) {
            $server - > push ($FD, tool:: showajax (['status' = > 2, 'message' = > 'invalid user identity, please login again']);
            $server->close($fd);
            return;
        }

        self::$uid = $req->get['friendId'];
        if (self::$uid == $userData['uid']) {
            $server - > push ($FD, tool:: showajax (['status' = > 2, 'message' = >'illegal operation! ']));
            $server->close($fd);
        }
        $server->bind($fd, $userData['uid']);
        $messages = Message::getMessage($userData['uid']);

        (new UserModel())->where('id', $userData['uid'])->update(['fd' => $req->fd]);
        $arr = $messages->toArray();
        sort($arr);

        $server->push($fd, Tool::showAjax(['status' => 1, 'message' => 'success', 'data' => $arr]));
    }

    public function onMessage(swoole_websocket_server $server, \swoole_websocket_frame $frame)
    {

        $message = $frame->data;
        if (empty($message)) return;
        $data = [
            'uid1' => $server->getClientInfo($frame->fd)['uid'],
            'uid2' => self::$uid,
            'message' => htmlspecialchars($message),
            'send_uid' => $server->getClientInfo($frame->fd)['uid']
        ];
        try {
            (new Message())->save($data);
        } catch (\Exception $e) {
            $server - > push ($frame - > FD, tool:: showajax (['status' = >'2 ','message' = >'failed to send data ']));
        }

        $messages = Message::getMessage($server->getClientInfo($frame->fd)['uid']);
        $friendData = UserModel::geUserDataFd(self::$uid);
        $arr = $messages->toArray();
        sort($arr);


        if ($friendData) {
            $server->push($friendData, Tool::showAjax(['status' => 1, 'message' => 'success', 'data' => $arr]));
        }
        $server->push($frame->fd, Tool::showAjax(['status' => 1, 'message' => 'success', 'data' => $arr]));
    }

    function onClose(\swoole_server $server, int $fd, int $reactorId)
    {
        (new UserModel())->where('fd', $fd)->update(['fd' => '']);
    }
}