首頁 > 後端開發 > php教程 > 身為socket長連接伺服器,Swoole如果要做到主動對已經連接過來的,用戶uid=123的那個用戶,推送一條訊息該怎麼寫?

身為socket長連接伺服器,Swoole如果要做到主動對已經連接過來的,用戶uid=123的那個用戶,推送一條訊息該怎麼寫?

WBOY
發布: 2016-08-04 09:22:09
原創
1222 人瀏覽過

額,這應該是菜鳥等級的問題,但是看了文檔我還是無從下手。

回覆內容:

額,這應該是菜鳥等級的問題,但是看了文檔我還是無從下手。

php的socket是資源型別:
resource(4) of type (Socket),也就是每個socket句柄都一個樣子。 。

而Linux C socket fd是個int整數,每個都是不同數字。

原生php做不到“主動對已經連接過來的,用戶uid=123的那個用戶,推送一條消息”,
但藉助Swoole利用linux C實現的socket,我們可以實現“主動對已經連接過來的,用戶uid=123的那個用戶,推一則訊息」。

這裡我們可以用System V最簡單的share memory來進程間共享資料IPC,維護一個用戶id與其socket連接的映射表。

程式碼如下:

<code><?php

$serv = new swoole_server("127.0.0.1", 1024);
$serv->set(array(
    'worker_num' => 8,   //工作进程数量
    'daemonize' => false, //是否作为守护进程
));

$shmid = shm_attach(getmypid(), 1024*66); # allocate 66kB for shared memory
define("SHARED_UID_CONNECTION_MAP", 12);
shm_put_var($shmid,SHARED_UID_CONNECTION_MAP, []);

$serv->on('connect', function ($serv, $fd) use($shmid) {
    echo "Client:Connect.\n";
});

$serv->on('receive', function ($serv, $fd, $from_id, $data) use($shmid)  {

    $serv->send($fd, 'Swoole: '.$data);
    // $serv->close($fd);

    $trimdata = trim($data);
    if ($trimdata == 'i am lucky man') {
        $map = shm_get_var($shmid,SHARED_UID_CONNECTION_MAP);
        $map[] = $fd;   #$map[$uidFromData] = $fd;
        shm_put_var($shmid,SHARED_UID_CONNECTION_MAP, $map);
    }


    if ($trimdata == 'broadcast to lucky man') {
        $map = shm_get_var($shmid,SHARED_UID_CONNECTION_MAP);
        // var_dump($map); $ $map is array whose valuse is int $fd
        foreach($map as $fd) {
            $serv->send($fd, "some body broadcast to you luck man");
        }
    }

    # broadcast to all users
    // $start_fd = 0;
    // while(true)
    // {
    //     $conn_list = $serv->connection_list($start_fd, 10);
    //     if($conn_list===false or count($conn_list) === 0)
    //     {
    //         echo "finish\n";
    //         break;
    //     }
    //     $start_fd = end($conn_list);
    //     var_dump($conn_list);
    //     foreach($conn_list as $fd)
    //     {
    //         $serv->send($fd, "broadcast");
    //     }
    // }

    // var_dump($serv->connections);
    // foreach ($serv->connections as $k => $v) {
    //    $lk = [$k,$v];
    //    var_dump($lk);
    // }

});
$serv->on('close', function ($serv, $fd) {
    echo "Client: Close.\n";
});
$serv->start();

</code>
登入後複製

接著就可以開n個客戶端,來測試下程式碼,例如我開3個telnet 127.0.0.1 1024,最後一個傳訊息給伺服器"i am lucky man",第一個再對伺服器發"broadcast to lucky man",那麼第三個就會收到""some body broadcast to you luck man",實現對特定用戶發送訊息。

就是這麼簡單,

Swoole大法好,異步io+多進程 也是最成熟的結局方案(致敬Nginx)
哈哈哈

uid只是你識別的uid而已,socket連結到服務,都有一個唯一的id,你要對客戶端發送訊息只能通過這個唯一的id,你可以在這兩者之間做個映射,那就可以了。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板