五分鐘教你寫超簡單的swoole聊天室

本來我是準備接着寫我那個多進程教程的,今天心血來潮想看看swoole的websocket,
我就點開了這個
WebSocket
我看了看官網的demo,以爲看起來很簡單嘛,javascript

<?php
//官網demo
$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 ,每行代碼意思一看就明白php

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

<!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 , 沒有問題java

這個時候我忽然想到一個事情,由於我作多進程的那個教程裏,在主進程中會將全部的子進程的句柄存起來,之後進行進程間通信用。
那麼 我將全部的客戶端的連接存起來存成數組,每當一個客戶端發送消息時,我就遍歷這個客戶端數組,將消息羣發一遍,不久實現了聊天室了嗎?
而後就,服務端代碼成了這個樣子web

<?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.phpwebsocket

<?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;
    $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,能夠了。swoole

固然,做爲聊天室,我這寫的也過於簡陋了,界面你們本身能夠寫的好看一些(由於我懶的寫界面)
還有,每次的發送聊天的記錄,應該存起來,這樣,若是有新的鏈接連過來的時候,先把之前的聊天記錄發過去,這樣,我想體驗更好一些

而後,你們能夠愉快的聊天了。哈哈

相關文章
相關標籤/搜索