江邊望海的技術人生
分享真知
搭建基于Swoole的Websocket聊天室

羣聊系統類似於聊天室,用戶可以在一起實時聊天。假如有三個用戶在一起聊天。用戶A發送的消息,用戶B和用戶C可以實時的看到。同樣的用戶B發送的消息,用戶A和用戶C也能實時看到。

為了實現這個需求就不得不使用 websocket 了。我們知道 http 是無狀態的、非實時的通訊協議。所以,很難滿足上面實時聊天的需求。而 websocket 則可以實現客戶端與服務器建立鏈接後,長期的保持鏈接。後端使用什麼工具來搭建 websocket 服務器呢?除了可以使用 node.js 外,也可以使用 swoole

基於 swoole 搭建羣聊系統只需要兩個文件就行。一個是服務端的 php 腳本文件,一個是客戶端的 html 文件。

server.php

<?php
$map    = array(); //客户端集合
$server = new swoole_websocket_server("192.168.1.110", 9502);
$server->on('open', function ($server, $req) {
    echo "connection open: {$req->fd}\n";
    global $map; //客户端集合
    $map[$req->fd] = $req->fd; //首次连上时存起来
});
$server->on('message', function ($server, $frame) {
    echo "received message: {$frame->data}\n";
    global $map; //客户端集合
    $data = '客户端 ' . $frame->fd . ' 号说:' . $frame->data;
    foreach ($map as $fd) {
        $server->push($fd, $data); //循环广播
    }
});
$server->on('close', function ($server, $fd) {
    echo "connection close: {$fd}\n";
});
$server->start();

服務器端的邏輯是監聽並接收客戶端的消息再推送給所有的客戶端。

client.html

<!DOCTYPE html>
<html>
<head>
  <title>群聊客户端</title>
  <meta charset="UTF-8">
  <script type="text/javascript">
  var exampleSocket = new WebSocket("ws://192.168.1.110:9502");
  exampleSocket.onopen = function (event) {
    exampleSocket.send("哈罗,大家好!我来了");
  };
  exampleSocket.onmessage = function (event) {
    console.log(event.data);
    var panel = document.getElementById("panel");
    panel.innerHTML = panel.innerHTML+event.data+"<br />";
  }
  </script>
</head>
<body>
  <div id="panel"></div>
<input type="text" id="content">
<button onclick="exampleSocket.send( document.getElementById('content').value );document.getElementById('content').value='';">发送</button>
</body>
</html>

現在的主流瀏覽器都支持 ws 鏈接服務端。所以客戶端直接用 javascript 腳本來實現交互。


效果圖如下:

服務器接收鏈接和消息,並向所有客戶端推送消息

服務器端截圖

客戶端接收消息

客戶端截圖

源代碼在這裏:https://github.com/jiangbianwanghai/swoole_demo