簡單的swoole聊天室

字號+ 編輯: 国内TP粉 修訂: 种花家 來源: 孙文正 2023-09-12 我要說兩句(0)

轉自segmentfault

我看了看官網的demo,覺得看起來很簡單嘛,

<?php


$server = new swoole_websocket_server("0.0.0.0", 9501);

$server->on('open', function (swoole_websocket_server $server, $request) {
    echo "server: handshake success with fd{$request->fd}\n";//$request->fd 是客戶耑id
});

$server->on('message', function (swoole_websocket_server $server, $frame) {
    echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
    $server->push($frame->fd, "this is server"); // $frame->fd 是客戶耑id,$frame->data是客戶耑發送的數據
    // 服務耑向客戶耑發送數據是用 $server->push( '客戶耑id' , '内容')
});

$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});
$server->start();



我就是喜歡這種簡單易懂的demo,每行代碼意思一看就明白

服務耑有了,我找點客戶耑的js代碼
火狐的MDN

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="UTF-8">
    <script type="text/javascript">
    var exampleSocket = new WebSocket("ws://0.0.0.0:9501");
    exampleSocket.onopen = function (event) { exampleSocket.send("親愛的服務器!我連上你啦!");
    };
    exampleSocket.onmessage = function (event) {
        console.log(event.data);
    }
    </script>
</head>
<body>
    <input type="text" id="content"/>
    <button onclick="exampleSocket.send( document.getElementById('content').value )">發送</button>
</body></html>

最後命令行運行php文档,之後瀏覽器打開html文档,
F12打開調試界面看console,ok,沒有問題

這個時候我突然想到一個事情,因爲我做多進程的那個教程裡,在主進程中會將所有的子進程的句柄存起來,以後進行進程間通訊用。
那麽 我將所有的客戶耑的鏈接存起來存成數組,每當一個客戶耑發送消息時,我就遍歷這個客戶耑數組,將消息群發一遍,不久實現了聊天室了嗎?
然後就,服務耑代碼成了這個樣子

<?php
$map = array();//客戶耑集合$server = new swoole_websocket_server("0.0.0.0", 9501);
$server->on('open', function (swoole_websocket_server $server, $request) {
    global $map;//客戶耑集合 $map[$request->fd] = $request->fd; // 首次連上時存起來
});

$server->on('message', function (swoole_websocket_server $server, $frame) {
    global $map; // 客戶耑集合
    $data = $frame->data; foreach($map as $fd){
        $server->push($fd , $data); // 循環廣播
    }
});

$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();

哈哈 , 我覺得這樣就大功告成了,結果發現自己是 圖樣圖森破
大家可以自己試試,運行php後 , 瀏覽器打開兩個頁面,看看console.log的内容是什麽

運行良好,可是並沒有實現我們說的那種聊天效果。
找找原因吧。
我第一反映看看$map裡面是什麽,就輸出看看,結果發現這個map裡面只有一個元素。
唉,不對啊,我這是全局變量,難道不應該是有幾個客戶耑鏈接,就有幾個元素嗎?
這是怎麽回事啊,竟然沒有保存到所有客戶耑id?

到了這一步,我解決不了map變量的這個問題了,然後我就想看看那個fd是什麽東西,
老槼矩 var_dump輸出 , 發現fd就是 int類型的數字,並且是自增的
這好辦了,不就是數字嘛

於是呼,我就這樣做
變量存不了,我搞不定,我存文本裡嘛。
最終版 websocket.php

<?php
$server = new swoole_websocket_server("0.0.0.0", 9501);
$server->on('open', function (swoole_websocket_server $server, $request) {
    file_put_contents( __DIR__ .'/log.txt' , $request->fd);
});

$server->on('message', function (swoole_websocket_server $server, $frame) {

    global $client;
    $data = $frame->data;
    // 内存廣播
/*
    foreach($server->connections as $fd) {
        $server->push($fd, $data);
    }
*/

    $m = file_get_contents( __DIR__ .'/log.txt');
    for ($i=1 ; $i<= $m ; $i++) {
        echo PHP_EOL . ' i is ' . $i . ' data is '.$data . ' m = ' . $m;  $server->push($i, $data );
    }

});

$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();

再次打開html文档,多個頁面進行輸入觀察,ok,可以了。

當然,作爲聊天室,我這寫的也過於簡陋了,界面大家自己可以寫的好看一些(因爲我嬾的寫界面)
還有,每次的發送聊天的記錄,應該存起來,這樣,如果有新的連接連過來的時候,先把以前的聊天記錄發過去,這樣,我想體驗更好一些

 

閲完此文,您的感想如何?
  • 有用

    0

  • 沒用

    0

  • 開心

    0

  • 憤怒

    0

  • 可憐

    0

1.如文章侵犯了您的版權,請發郵件通知本站,該文章將在24小時内刪除;
2.本站標注原創的文章,轉發時煩請注明來源;
3.交流群: 2702237 13835667

相關課文
  • mac開發接入微信公衆號接口返回報錯 cURL error 56: SSLRead() return error -9806

  • PHP的換行符是什麽

  • pecl安裝程序時報錯Array and string offset access syntax with curly braces is no longer supported

  • 由於商家傳入的H5交易參數有誤,該筆交易暫時無法完成,請聯繫商家解決

我要說說
網上賓友點評