Swoole:面向生产环境的 PHP 异步网络通信引擎
使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。Swoole 可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等领域。使用 PHP + Swoole 作为网络通信框架,可以使企业 IT 研发团队的效率大大提升,更加专注于开发创新产品。
新建PushServer.php<?php /** * Created by PhpStorm. * User: zhengbingdong * Date: 2020/08/15 * Time: 01:06 */ class PushServer { private static $instance; private static $server; public $messageHandler; //处理消息的对象 //不能够在类外面创建该对象的实例 private function __construct() { //>>1.创建websocket对象 self::$server = new swoole_websocket_server('0.0.0.0', 9502); //>>2.注册事件 self::$server->on('open', [$this, 'onOpen']); //将当前类的onOpen方法作为open的事件处理函数 self::$server->on('message', [$this, 'onMessage']); self::$server->on('close', [$this, 'onClose']); self::$server->on('workerStart',[$this,'onWorkerStart']); } //当客户端连上之后要执行的方法 public function onOpen($server, $req) { echo "connection open: {$req->fd}\n"; } //客户端向服务器发送消息要执行的方法 public function onMessage($server, $frame) { //将传输的json转成数组 $data = json_decode($frame->data,true); //检查方法是否存在 if (method_exists($this->messageHandler,$data['cmd'])) { call_user_func([$this->messageHandler,$data['cmd']],self::$server,$data['data']); } else { $outMessage = json_encode([ 'status' => 'error', 'msg' => '非法操作' ]); echo $outMessage."\n"; self::$server->push($frame->fd, $outMessage); } } //客户端和服务器端断开连接时执行的方法 public function onClose($server,$fd) { $online = []; foreach ($server->connections as $clientId) { array_push($online, $clientId); $outMessage = json_encode( [ 'type' => 'close', 'fid' => $clientId, 'online' => $online, 'num' => count($server->connections) ] ); self::$server->push($clientId, $outMessage); } echo "当前服务器共有 " . count($server->connections) . " 个连接\n"; echo '客户端或服务器断开连接'.$fd."\n"; } //服务器启动之后执行 public function onWorkerStart() { echo 'onWorkerStart----------'.date('Y-m-d H:i:s')."\n"; require './MessageHandler.php'; $this->messageHandler = new MessageHandler(); } public static function getInstance() { if (!self::$instance instanceof self) { self::$instance = new self(); } return self::$instance; } public function start() { self::$server->start(); } } PushServer::getInstance()->start(); //启动推送服务
新建MessageHandler.php
<?php /** * Created by PhpStorm. * User: zhengbingdong * Date: 2020/08/15 * Time: 01:06 */ class MessageHandler { public function join($server, $data) { foreach ($server->connections as $fd) { $outMessage = json_encode( [ 'type' => 'join', 'client_id' => $fd, 'name' => $data['name'], 'num' => count($server->connections) ] ); $server->push($fd, $outMessage); } } public function sendMessage($server, $data){ foreach ($server->connections as $fd) { $outMessage = json_encode( [ 'name' => $data['name'], 'content' => $data['content'] ] ); $server->push($fd, $outMessage); } } public function changeNickName($server, $data){ foreach ($server->connections as $fd) { $outMessage = json_encode( [ 'type' => 'changeNickName', 'before' => $data['before'], 'after' => $data['after'] ] ); $server->push($fd, $outMessage); } } public function outLine(){ echo '-------------------------离开了'; } }
新建聊天室页面
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title> 匿名即时聊天室 </title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"> </script> </head> <style type="text/css" media="all"> body { padding: 0; margin: 0; } #online { width: 100%; margin: 0 auto; } #messgae { background: #eee; padding: 5px; margin-bottom: 15px; height: 380px; overflow: scroll; } #online-num { font-size: 15px; padding-left: 10px; } #socket { background: #f5f5f5; padding: 20px; } #name { width: 98%; } #content { width: 98%; } #sender { width: 100%; } </style> <body> <div id="online"> <div id="messgae"> <h3 id="title"> 匿名聊天室 <span id="online-num"> 当前在线 <span id="num"> </span> 人 </span> </h3> </div> <div id="socket"> <p> 网名: <input type="text" id="name" value=""> </p> <p> 内容: <textarea name="" id="content" rows="8" cols="40"> </textarea> </p> <p> <input type="submit" name="" id="sender" value="发送" /> </p> </div> </div> <script> var cookie = { set: function(key, val, time) { //设置cookie方法 var date = new Date(); //获取当前时间 var expiresDays = time; //将date设置为n天以后的时间 date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000); //格式化为cookie识别的时间 document.cookie = key + "=" + val + ";expires=" + date.toGMTString(); //设置cookie }, get: function(key) { //获取cookie方法 /*获取cookie参数*/ var getCookie = document.cookie.replace(/[ ]/g, ""); //获取cookie,并且将获得的cookie格式化,去掉空格字符 var arrCookie = getCookie.split(";") //将获得的cookie以"分号"为标识 将cookie保存到arrCookie的数组中 var tips; //声明变量tips for (var i = 0; i < arrCookie.length; i++) { //使用for循环查找cookie中的tips变量 var arr = arrCookie[i].split("="); //将单条cookie用"等号"为标识,将单条cookie保存为arr数组 if (key == arr[0]) { //匹配变量名称,其中arr[0]是指的cookie名称,如果该条变量为tips则执行判断语句中的赋值操作 tips = arr[1]; //将cookie的值赋给变量tips break; //终止for循环遍历 } } return tips; }, delete: function(key) { //删除cookie方法 var date = new Date(); //获取当前时间 date.setTime(date.getTime() - 10000); //将date设置为过去的时间 document.cookie = key + "=v; expires =" + date.toGMTString(); //设置cookie } }; $(function() { $('#name').val(cookie.get("userNickname") ? cookie.get("userNickname") : '游客' + <?=date('YmdHis'); ? >) $('#name').blur(function() { var name = $('#name').val(); var before = cookie.get("userNickname") ? cookie.get("userNickname") : name; cookie.set("userNickname", name, 24) websocket.send('{"cmd":"changeNickName","data":{"before":"' + before + '","after":"' + name + '"}}'); }); var websocket = new WebSocket("ws://192.168.31.107:9502"); websocket.onopen = function() { console.log('连接上服务器'); var intNickName = cookie.get("userNickname") ? cookie.get("userNickname") : '游客' + <?=date('YmdHis'); ? >; cookie.set("userNickname", intNickName, 24); websocket.send('{"cmd":"join","data":{"name":"' + intNickName + '"}}'); } websocket.onmessage = function(event) { var getName = cookie.get("userNickname"); var data = JSON.parse(event.data); //console.log(data) if (data.type == 'join') { $('#messgae').append('<p>系统提示:' + data.name + '加入聊天室</p>'); $('#num').text(data.num); } else if (data.type == 'close') { $('#messgae').append('<p>系统提示:' + data.fid + '离开了聊天室</p>'); } else if (data.type == 'changeNickName') { $('#messgae').append('<p>系统提示:' + data.before + '更改了网名为《' + data.after + '》</p>'); } else { $('#messgae').append('<p>' + data.name + ':' + data.content + '</p>'); } goBottom(); } websocket.onclose = function() { console.log('断开了链接'); } $('#sender').click(function() { var name = $('#name').val(); var sendContent = $('#content').val() websocket.send('{"cmd":"sendMessage","data":{"name":"' + name + '","content":"' + sendContent + '"}}'); $('#content').val(''); goBottom(); }) function goBottom() { var div = document.getElementById('messgae'); div.scrollTop = div.scrollHeight; } }); </script> </body> </html>
最后修改:2020 年 08 月 18 日
© 允许规范转载