Workerman建立聊天室實例

// 標記是全局啓動
define('GLOBAL_START', 1);

require_once __DIR__ . '/Workerman/Connection.php';
require_once __DIR__ . '/Workerman/Autoloader.php';

use Workerman\Worker;
use Workerman\Lib\Timer;

// 心跳間隔25秒
define('HEARTBEAT_TIME', 25);

// 設置時區
date_default_timezone_set('PRC');

// 以websocket協議爲例
// Create a Websocket server
$ws = new Worker("websocket://118.xxx.xxx.xx:4980");

// 啓動4個進程對外提供服務
$ws->count = 4;

// 已鏈接客戶端 ,便於統計在線用戶
$ws->hasConnections = array();

// 當新客戶端連上來時分配uid,並保存鏈接,並通知全部客戶端
$ws->onConnect = function($connection)
{
    global $ws;
    // 爲這個連接分配一個uid
    $connection->uid = ++$global_uid;

    foreach ($ws->connections as $conn) {
        $conn->send("用戶{$connection->uid} 已上線");
    }
    $connection->close(); // 關閉socket鏈接
    // echo "New connection\n";
 };

// 當客戶端發送消息過來時,轉發給全部人 (聊天主要使用的功能)
$ws->onMessage = function($connection, $message)
{
    global $ws,$db;
    $data = json_decode($message, true);

    $data['time'] = date('Y-m-d H:i:s');
    $insert = array(
        'uid'         =>$data['uid'],
        'avatar'      =>$data['avatar'],
        'name'        =>$data['name'],
        'type'        =>$data['type'],
        'content'     =>$data['content'],
        'img_path'    =>$data['img_path'],
        'voice_path'  =>$data['voice_path'],
        'topic_id'    =>$data['topic_id'],
        'is_question' =>$data['is_question'],
        'status'      =>$data['status'],
        'time'        =>$data['time']
    );

    switch ($data['type']) {
        case 'save':
            // 把房間和用戶信息保存下來
            $ws->hasConnections[$connection->id] = array('name' => $data['name'], 'uid' => $data['uid'], 'topic_id' => $data['topic_id'], 'avatar' => $data['avatar']);
            sendMessage($data, $data['topic_id']);
            // $back_data = array('content' => $content, 'client_id' => $connection->id, 'client_name' => $data['name'], 'type' => 'login', 'clients' => $ws->hasConnections, 'time' => date('Y-m-d H:i:s'));

            break;

        case 'text':
            sendMessage($data, $data['topic_id']);
            $insert_id = $db->insert('chat_record')->cols($insert)->query();  // 存數據庫 save data
            break;

        case 'img':
            sendMessage($data, $data['topic_id']);
            $insert_id = $db->insert('chat_record')->cols($insert)->query();  // 存數據庫 save data
            break;

        case 'voice':
            sendMessage($data, $data['topic_id']);
            $insert_id = $db->insert('chat_record')->cols($insert)->query();  // 存數據庫 save data
            break;
        default:
            break;
    }

    // $connection->close(); // 關閉socket鏈接
};

// 當客戶端斷開時,廣播給全部客戶端
// $ws->onClose = function($connection)
// {
//     global $ws;
//     foreach ($ws->connections as $conn) {
//         $conn->send("用戶[{$connection->uid}] 消消走了");
//     }
//     $connection->close(); // 關閉socket鏈接
// };

// 給房間的每一個人發消息
function sendMessage($data, $topic_id){
    global $ws;
    $data = json_encode($data);
    foreach ($ws->connections as $id => $conn) {
        if ($ws->hasConnections[$id]['topic_id'] == $topic_id) {
            $conn->send($data);
            // $conn->send($ws->hasConnections[$id]);
        }
    }
}

// 進程啓動後設置一個每秒運行一次的定時器(心跳, 保持長鏈接)
$ws->onWorkerStart = function($ws) {
    global $db;
    // ip, 端口號, 帳號, 密碼, 庫名
    $db = new \Workerman\MySQL\Connection('127.0.0.1', '3306', 'username', 'password', 'database');

    Timer::add(1, function()use($ws){
    // global $ws;
        $arr = array('type'=>'keep','content'=>'ping');
        $arr = json_encode($arr);
        foreach($ws->connections as $connection) {
            $connection->send($arr);
        }
    });
};


// Run worker
Worker::runAll();
相關文章
相關標籤/搜索