TP是最新版本的;
大概實現的有,用戶註冊,註冊完畢以後跳轉到登陸頁面;
登陸以後生成身份令牌(token)存到Redis;
在聊天界面沒有任何ajax請求,只要在握手的時候有一個http請求,實在是搞不懂一些人,在聊天界面發佈消息用ajax去發佈,php
作了一些處理,一個瀏覽器裏面只能用一個帳號,因此測試的時候必須用兩個瀏覽器html
以後跳轉到聊天界面,而後創建WebSocket握手,在握手的同時攜帶toekn,以及對方的ID(朋友的ID) ;react
後臺服務器在OnOpen的時候作一系列的操做,例如(檢測token,檢測朋友的ID,將本身的ID和fd更新到數據表,fd綁定uid等..);
這些檢測都經過以後獲取聊天記錄,爲了效率是拉取和朋友的15條聊天記錄;web
在OnMessage中獲取了發送的數據!
在發送以後檢測對方是否在線,若是不在線就不用發送給對方,若是對方在線就將信息push給他!ajax
心跳檢測: 每5秒檢測一次,若是在100秒沒有任何操做將斷開鏈接,斷開鏈接的同時將數據庫中的fd清空!數據庫
代碼很簡單,,,可是有個別的問題沒有解決,好比在線統計(connections) 瀏覽器
下面貼上Socket_Server.php的代碼 其餘的都是沒有什麼邏輯的代碼!服務器
完整的等以後寫完了再發出來吧,你們共同進步!websocket
<?php /** * User: 李昊天 * Date: 18/7/03 * Time: 上午4:19 * Email: haotian0607@gmail.com */ namespace app\index\controller; use app\index\model\Message; use app\index\model\User as UserModel; use app\tool\Tool; use think\facade\Cache; use swoole_websocket_server; class Swoole extends \think\swoole\Server { protected static $token; protected $host = '127.0.0.1'; protected $port = 9508; protected $serverType = 'socket'; protected static $uid = ''; protected $option = [ 'worker_num' => 4, // 設置啓動的Worker進程數 'daemonize' => false, //守護進程化。 'backlog' => 128, //Listen隊列長度, 'dispatch_mode' => 2, 'heartbeat_check_interval' => 5, 'heartbeat_idle_time' => 100, ]; public function onOpen(swoole_websocket_server $server, \swoole_http_request $req) { $fd = $req->fd; $token = $req->get['token'] ?? ''; //拿到客戶端用戶ID if (!$token) { $server->push($fd, Tool::showAjax(['status' => 3, 'message' => '請先登陸!'])); $server->close($fd); return; } $userData = Cache::get($token); if (!$userData) { $server->push($fd, Tool::showAjax(['status' => 2, 'message' => '用戶身份無效,請從新登陸!'])); $server->close($fd); return; } self::$uid = $req->get['friendId']; if (self::$uid == $userData['uid']) { $server->push($fd, Tool::showAjax(['status' => 2, 'message' => '非法操做!'])); $server->close($fd); } $server->bind($fd, $userData['uid']); $messages = Message::getMessage($userData['uid']); (new UserModel())->where('id', $userData['uid'])->update(['fd' => $req->fd]); $arr = $messages->toArray(); sort($arr); $server->push($fd, Tool::showAjax(['status' => 1, 'message' => 'success', 'data' => $arr])); } public function onMessage(swoole_websocket_server $server, \swoole_websocket_frame $frame) { $message = $frame->data; if (empty($message)) return; $data = [ 'uid1' => $server->getClientInfo($frame->fd)['uid'], 'uid2' => self::$uid, 'message' => htmlspecialchars($message), 'send_uid' => $server->getClientInfo($frame->fd)['uid'] ]; try { (new Message())->save($data); } catch (\Exception $e) { $server->push($frame->fd, Tool::showAjax(['status' => '2', 'message' => '發送數據失敗!'])); } $messages = Message::getMessage($server->getClientInfo($frame->fd)['uid']); $friendData = UserModel::geUserDataFd(self::$uid); $arr = $messages->toArray(); sort($arr); if ($friendData) { $server->push($friendData, Tool::showAjax(['status' => 1, 'message' => 'success', 'data' => $arr])); } $server->push($frame->fd, Tool::showAjax(['status' => 1, 'message' => 'success', 'data' => $arr])); } function onClose(\swoole_server $server, int $fd, int $reactorId) { (new UserModel())->where('fd', $fd)->update(['fd' => '']); } }