Home  >  Article  >  PHP Framework  >  Use Workman to create a chat room

Use Workman to create a chat room

步履不停
步履不停Original
2019-06-21 14:52:236190browse

Use Workman to create a chat room

Why write this article?

I have learned Workman several times, but failed every time (I did not achieve the desired function, please forgive me for being stupid). But this time it also took several hours to implement functions that had not been done before. In fact, there are two simple functions: sending messages one-to-one and broadcasting messages (group chat). This function has been implemented with swoole for a long time, and it is also because I have always wanted to use think-worker. Think about it, you still have to figure it out yourself. The framework that others have made may be a castrated version.

Don’t ask me why I don’t use swoole, because workman can run in Windows.

(1) First, let’s briefly talk about the installation of thinkphp workerman.

Install thinkphp5.1

composer create-project topthink/think=5.1.x-dev tp5andworkman

Install think-worker

composer require topthink/think-worker=2.0.*

Install workman directly

composer require workerman/workerman

(2) Let’s look at it first think-worker code

  • config/worker_server.php

  • First, let’s take an example of a server broadcasting a message every 10 seconds. Broadcast a message regularly

'onWorkerStart'  => function ($worker) {
    \Workerman\Lib\Timer::add(10, function()use($worker){
        // 遍历当前进程所有的客户端连接,发送自定义消息
        foreach($worker->connections as $connection){
            $send['name'] = '系统信息';
            $send['content'] = '这是一个定时任务信息';
            $send['time'] = time();
            $connection->send(json_encode($send));
        }
    });
}

But during onMessage, we cannot obtain the $worker object, so we cannot broadcast the message.

'onMessage'      => function ($connection, $data) {
    $origin = json_decode($data,true);
    $send['name'] = '广播数据';
    $send['content'] = $origin['content'];
    $message = json_encode($send);

    foreach($worker->connections as $connection)
    {
        $connection->send($message);
    }
}

I tried various methods, but none seemed to work

'onMessage'      => function ($connection, $data)use($worker) {
    // 这样是获取不到 $worker 对象的
    // ...省略代码
}

So we can only abandon the think-worker framework that thinkphp encapsulated for us, and we have to write it ourselves (or modify the internal code of the framework)

Modify the code inside the framework: /vendor/topthink/think-worker/src/command/Server.php, mainly to add the onMessage method yourself

use() That is to pass external variables to the function for internal use, or use global $worker

$worker = new Worker($socket, $context);

$worker->onMessage = function ($connection, $data)use($worker) {
    $origin = json_decode($data,true);
    $send['name'] = '广播数据';
    $send['content'] = $origin['content'];
    $send['uid'] = $connection->uid;
    $message = json_encode($send);
    foreach($worker->connections as $connection)
    {
        $connection->send($message);
    }
};

In this way, we can get the $worker object

$worker->onMessage = function ($connection, $data)use($worker) { ... }

( 3) $connection is bound to uid

In fact, you have already seen that $worker->connections obtains the connections of all current users, and connections is one of the links.

Record websocket connection time:

$worker->onConnect = function ($connection) {
    $connection->login_time = time();
};

Get websocket connection time:

$worker->onMessage = function ($connection, $data)use($worker) {
    $login_time = $connection->login_time;
};

It can be seen that we can bind data to an attribute of the $connection connection, For example:

$connection->uid = $uid;

When the JavaScript side successfully connects to the websocket server, it immediately sends its uid to the server for binding:

$worker->onMessage = function ($connection, $data)use($worker) {
    $origin = json_decode($data,true);
    if(array_key_exists('bind',$origin)){
        $connection->uid = $origin['uid'];
    }
};

(4) Unicast message, that is Custom sending

$worker->onMessage = function ($connection, $data)use($worker) {
    $origin = json_decode($data,true);
    $sendTo = $origin['sendto']; // 需要发送的对方的uid
    $content = $origin['content']; // 需要发送到对方的内容
    foreach($worker->connections as $connection)
    {
        if( $connection->uid == $sendTo){
            $connection->send($content);
        }
    }
};

At this point, the custom object sending message based on workman has been completed.

Since the php file is stored in composer, you only need to copy the file, put it in application/command, modify the namespace, and save it to your own project

(5) Comparison with swoole

1. Workman can run in Windows system, but swoole cannot.

2. workman: $worker->connections gets all connections, $connection->id gets its own connection id; swoole: $server->connections gets all connections, $connection->fd Get your own connection id.

3. The onWorkerStart method is executed when workman starts, and the timer can be written into it; swoole uses WorkerStart to start the timer.

For chat rooms or timers, workman is still more convenient.

For more ThinkPHP related technical articles, please visit the ThinkPHP usage tutorial column to learn!

The above is the detailed content of Use Workman to create a chat room. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn