php安装swoole
作者QQ:67065435 QQ群:821635552
本站内容全部为作者原创,转载请注明出处!
下载swoole安装
pecl install swoole
在php.ini添加swoole.so
extension=swoole.so
PHP原生写法
<?php function on_open(swoole_websocket_server $server, $request) { //客户端已经连接 } function on_close($server, $fd) { //客户端已经断开 } function on_message(swoole_websocket_server $server, $frame) { foreach ($server->connections as $fd) { //消息发送者客户端id:$request->fd //消息接收者客户端id:$fd $server->push($fd, $frame->data); } } $server = new swoole_websocket_server("0.0.0.0", 1234); $server->on('open', 'on_open'); $server->on('close', 'on_close'); $server->on('message', 'on_message'); $server->start();
PHP匿名函数(闭包)写法
<?php $server = new swoole_websocket_server("0.0.0.0", 1234); $server->on('open', function (swoole_websocket_server $server, $request) { //客户端已经连接 }); $server->on('close', function ($server, $fd) { //客户端已经断开 }); $server->on('message', function (swoole_websocket_server $server, $frame) { foreach ($server->connections as $fd) { $server->push($fd, $frame->data); } }); $server->start();
PHP面向对象写法
<?php class SwooleServer { public function onOpen(swoole_websocket_server $server, $request) { //客户端已经连接 } public function onClose($server, $fd) { //客户端已经断开 } public function onMessage(swoole_websocket_server $server, $request) { $data = $request->data; foreach ($server->connections as $fd) { $server->push($fd, $data); } } } $swoole_server = new SwooleServer(); $server = new swoole_websocket_server("0.0.0.0", 1234); $server->on('open', array($swoole_server, 'onOpen')); $server->on('close', array($swoole_server, 'onClose')); $server->on('message', array($swoole_server, 'onMessage')); $server->start();
PHP守护进程写法(支持ssl安全传输,支持守护进程启动)
#!/usr/local/php7/bin/php <?php //打印帮助信息 $help = <<<EOF 帮助信息: --port swoole对外开放的端口 --host swoole对外开放的地址 --ssl 是否用ssl传输加密 --cert ssl公钥文件的路径 --key ssl私钥文件的路径 --daemon 以守护进程运行脚本 --help 打印脚本的帮助信息\n EOF; //检查扩展安装 if (!extension_loaded('pcntl')) { exit("请安装pcntl扩展\n"); } if (!extension_loaded('swoole')) { exit("请安装swoole扩展\n"); } //处理传入参数 $opt = getopt('', ["port::", "host::", "ssl::", "cert::", "key::", "daemon::", "help::"]); if (isset($opt['help'])) { exit($help); } try { $opt = [ 'port' => !empty($opt['port']) ? $opt['port'] : (isset($opt['ssl']) ? 444 : 88), 'host' => !empty($opt['host']) ? $opt['host'] : '0.0.0.0', 'ssl' => isset($opt['ssl']) ? 'y' : 'n', 'cert' => !empty($opt['cert']) ? $opt['cert'] : null, 'key' => !empty($opt['key']) ? $opt['key'] : null, 'daemon' => isset($opt['daemon']) ? 'y' : 'n', ]; if ($opt['ssl'] === 'y') { //外部封装安全传输协议 $server = new swoole_websocket_server($opt['host'], $opt['port'], SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); $server->set(['ssl_key_file' => $opt['key'], 'ssl_cert_file' => $opt['cert']]); } else { //外部不封装安全传输协议 $server = new swoole_websocket_server($opt['host'], $opt['port'], SWOOLE_PROCESS, SWOOLE_SOCK_TCP); } $server->on('open', function (swoole_websocket_server $server, $request) { //客户端已经连接 }); $server->on('close', function ($server, $fd) { //客户端已经断开 }); $server->on('message', function (swoole_websocket_server $server, $frame) { //客户端发来消息 foreach ($server->connections as $fd) { $fd_status = $server->connection_info($fd); if (isset($fd_status['websocket_status']) && $fd_status['websocket_status'] == 3) { //客户端是握手成功等待数据帧 $server->push($fd, $frame->data); } unset($fd_status); } }); if ($opt['daemon'] === 'y') { //以守护进程启动 $pid = pcntl_fork(); if ($pid < 0) { exit(0); } elseif ($pid > 0) { exit(0); } $sid = posix_setsid(); if ($sid == -1) { exit(0); } else { $server->start(); } } else { //以普通进程启动 $server->start(); } } catch (\Exception $e) { exit($help); }
聊天功能,html文件
<!DOCTYPE html> <html> <head> <title>聊天</title> <meta charset="UTF-8"> <script type="text/javascript"> let str = ''; let socketTalk = new WebSocket("ws://[ip]:1234"); socketTalk.onmessage = function (event) { str = str + '<p>' + event.data + '</p>'; console.log(event.data); document.getElementById("talk").innerHTML = str; } </script> </head> <body> <input type="text" id="content"> <button onclick="socketTalk.send( document.getElementById('content').value )">发送</button> <div id="talk"></div> </body> </html>
游戏功能,html文件(3D联网游戏,以平面逻辑说明)
<!DOCTYPE html> <html> <head> <title>Move</title> <meta charset="UTF-8"> <style> /*默认样式*/ * { margin: 0; padding: 0 } /*用户盒子*/ #box { width: 100%; height: 100%; } /*用户数据*/ .user { position: fixed; top: 0; left: 0; width: 4rem; height: 4rem; background-color: rgba(0, 0, 0, 0.3); } </style> </head> <body> <div id="box"></div> <script> //分配用户id(可以通过别的逻辑生成用户id) let user_id = window.localStorage.getItem('user_id') ? window.localStorage.getItem('user_id') : Date.now(); window.localStorage.setItem('user_id', user_id); //创建我的节点 let user = document.createElement("div"); user.setAttribute("class", "user"); user.setAttribute("id", user_id); let x = Math.ceil(Math.random() * 600); let y = Math.ceil(Math.random() * 600); user.style.left = x + "px"; user.style.top = y + "px"; user.style.backgroundColor = "#ff0"; let box = document.getElementById("box"); box.appendChild(user); //消息处理 let msg = new WebSocket("ws://[server]:[port]"); msg.onopen = function (event) { document.getElementById(user_id).style.backgroundColor = "#ff0";//自己是黄色,别人是灰色 document.getElementById(user_id).style.left = x + "px"; document.getElementById(user_id).style.top = y + "px"; //告诉其他用户我的动作 let obj = { "user_id": user_id,//用户标识 "say": "",//用户说话 "move": {//移动数据 "x": x,//横向位移 "y": y,//纵向位移 "z": 0,//高度位移 "t": 0,//仰角大小(相对正北) "r": 0,//转角大小(相对正北) } }; msg.send(JSON.stringify(obj)); }; msg.onmessage = function (event) { //收到请求,解析请求 let action = JSON.parse(event.data); //请求类型,用户move if (action.user_id && action.user_id != user_id) { if (document.getElementById(action.user_id)) { //他人节点已存在,直接做移动 document.getElementById(action.user_id).style.left = action.move.x + "px"; document.getElementById(action.user_id).style.top = action.move.y + "px"; } else { //他人节点不存在,创建并移动 let user = document.createElement("div"); user.setAttribute("class", "user"); user.setAttribute("id", action.user_id); let box = document.getElementById("box"); box.appendChild(user); document.getElementById(action.user_id).style.left = action.move.x + "px"; document.getElementById(action.user_id).style.top = action.move.y + "px"; } } }; //手机move function onTouchMove(point) { document.getElementById(user_id).style.left = (point.changedTouches[0].clientX) + "px"; document.getElementById(user_id).style.top = (point.changedTouches[0].clientY) + "px"; //告诉其他用户我的动作 let obj = { "user_id": user_id,//用户标识 "say": "",//用户说话 "move": {//移动数据 "x": point.changedTouches[0].clientX, "y": point.changedTouches[0].clientY, "z": 0,//高度位移 "t": 0,//仰角大小(相对正北) "r": 0,//转角大小(相对正北) } }; msg.send(JSON.stringify(obj)); } document.getElementById(user_id).addEventListener("touchmove", onTouchMove, false); //电脑move function onMouseDown(point) { document.onmousemove = function (event) { document.getElementById(user_id).style.left = event.clientX + "px"; document.getElementById(user_id).style.top = event.clientY + "px"; //告诉其他用户我的动作 let obj = { "user_id": user_id,//用户标识 "say": "",//用户说话 "move": {//移动数据 "x": event.clientX, "y": event.clientY, "z": 0,//高度位移 "t": 0,//仰角大小(相对正北) "r": 0,//转角大小(相对正北) } }; msg.send(JSON.stringify(obj)); }; document.onmouseup = function () { document.onmousemove = null; document.onmouseup = null; }; } document.getElementById(user_id).addEventListener("mousedown", onMouseDown, false); </script> </body> </html>
打开防火墙1234端口
firewall-cmd --zone=public --add-port=1234/tcp --permanent systemctl restart firewalld
启动swoole服务
php index.php
PHP守护进程写法(增加对房间区分功能的支持)
#!/usr/local/php7/bin/php <?php //打印帮助信息 $help = <<<EOF 帮助信息: --port swoole对外开放的端口 --host swoole对外开放的地址 --ssl 是否用ssl传输加密 --cert ssl公钥文件的路径 --key ssl私钥文件的路径 --daemon 以守护进程运行脚本 --help 打印脚本的帮助信息\n EOF; //检查扩展安装 if (!extension_loaded('pcntl')) { exit("请安装pcntl扩展\n"); } if (!extension_loaded('swoole')) { exit("请安装swoole扩展\n"); } //处理传入参数 $opt = getopt('', ["port::", "host::", "ssl::", "cert::", "key::", "daemon::", "help::"]); if (isset($opt['help'])) { exit($help); } try { $opt = [ 'port' => !empty($opt['port']) ? $opt['port'] : (isset($opt['ssl']) ? 444 : 88), 'host' => !empty($opt['host']) ? $opt['host'] : '0.0.0.0', 'ssl' => isset($opt['ssl']) ? 'y' : 'n', 'cert' => !empty($opt['cert']) ? $opt['cert'] : null, 'key' => !empty($opt['key']) ? $opt['key'] : null, 'daemon' => isset($opt['daemon']) ? 'y' : 'n', ]; if ($opt['ssl'] === 'y') { //外部封装安全传输协议 $server = new swoole_websocket_server($opt['host'], $opt['port'], SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); $server->set(['ssl_key_file' => $opt['key'], 'ssl_cert_file' => $opt['cert'], 'dispatch_mode' => 5]); } else { //外部不封装安全传输协议 $server = new swoole_websocket_server($opt['host'], $opt['port'], SWOOLE_PROCESS, SWOOLE_SOCK_TCP); $server->set(['dispatch_mode' => 5]); } $server->on('open', function (swoole_websocket_server $server, $request) { //客户端已经连接 if (isset($request->get['room_id']) && isset($request->get['user_id'])) { $server->bind($request->fd, $request->get['user_id']); $queue = (array)json_decode(@file_get_contents("/var/log/swoole.log"), true); $queue[$request->fd] = [ 'room_id' => $request->get['room_id'], 'user_id' => $request->get['user_id'], ]; @file_put_contents("/var/log/swoole.log", json_encode($queue, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); } }); $server->on('close', function ($server, $fd) { //客户端已经断开 $queue = (array)json_decode(@file_get_contents("/var/log/swoole.log"), true); unset($queue[$fd]); @file_put_contents("/var/log/swoole.log", json_encode($queue, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); }); $server->on('message', function (swoole_websocket_server $server, $request) { //客户端发来消息 $data = (array)json_decode($request->data, true); $queue = (array)json_decode(@file_get_contents("/var/log/swoole.log"), true); foreach ($server->connections as $fd) { $fd_status = $server->connection_info($fd); if ( isset($fd_status['websocket_status']) && $fd_status['websocket_status'] == 3 && isset($data['room_id']) && isset($queue[$fd]['room_id']) && $data['room_id'] == $queue[$fd]['room_id'] ) { //客户端是握手成功等待数据帧 $server->push($fd, $request->data); } unset($fd_status); } }); if ($opt['daemon'] === 'y') { //以守护进程启动 $pid = pcntl_fork(); if ($pid < 0) { exit(0); } elseif ($pid > 0) { exit(0); } $sid = posix_setsid(); if ($sid == -1) { exit(0); } else { $server->start(); } } else { //以普通进程启动 $server->start(); } } catch (\Exception $e) { echo "\33[31;49m" . $e->getMessage() . "\33[0m" . PHP_EOL; exit($help); }
游戏功能,html文件(增加对房间区分功能的支持)
<!DOCTYPE html> <html> <head> <title>Move</title> <meta charset="UTF-8"> <style> /*默认样式*/ * { margin: 0; padding: 0 } /*用户盒子*/ #box { width: 100%; height: 100%; } /*用户数据*/ .user { position: fixed; top: 0; left: 0; width: 4rem; height: 4rem; background-color: rgba(0, 0, 0, 0.3); } </style> </head> <body> <div id="box"></div> <script> //分配房间id(可以通过别的逻辑生成房间id) let room_id = 1; //分配用户id(可以通过别的逻辑生成用户id) let user_id = window.localStorage.getItem('user_id') ? window.localStorage.getItem('user_id') : Date.now(); window.localStorage.setItem('user_id', user_id); //创建我的节点 let user = document.createElement("div"); user.setAttribute("class", "user"); user.setAttribute("id", user_id); let x = Math.ceil(Math.random() * 600); let y = Math.ceil(Math.random() * 600); user.style.left = x + "px"; user.style.top = y + "px"; user.style.backgroundColor = "#ff0"; let box = document.getElementById("box"); box.appendChild(user); //消息处理 let msg = new WebSocket("ws://[server]:[port]?room_id=" + room_id + "&user_id=" + user_id); msg.onopen = function (event) { document.getElementById(user_id).style.backgroundColor = "#ff0";//自己是黄色,别人是灰色 document.getElementById(user_id).style.left = x + "px"; document.getElementById(user_id).style.top = y + "px"; //告诉其他用户我的动作 let obj = { "room_id": room_id,//房间标识 "user_id": user_id,//用户标识 "say": "",//用户说话 "move": {//移动数据 "x": x,//横向位移 "y": y,//纵向位移 "z": 0,//高度位移 "t": 0,//仰角大小(相对正北) "r": 0,//转角大小(相对正北) } }; msg.send(JSON.stringify(obj)); }; msg.onmessage = function (event) { //收到请求,解析请求 let action = JSON.parse(event.data); //请求类型,用户move if (action.user_id && action.user_id != user_id) { if (document.getElementById(action.user_id)) { //他人节点已存在,直接做移动 document.getElementById(action.user_id).style.left = action.move.x + "px"; document.getElementById(action.user_id).style.top = action.move.y + "px"; } else { //他人节点不存在,创建并移动 let user = document.createElement("div"); user.setAttribute("class", "user"); user.setAttribute("id", action.user_id); let box = document.getElementById("box"); box.appendChild(user); document.getElementById(action.user_id).style.left = action.move.x + "px"; document.getElementById(action.user_id).style.top = action.move.y + "px"; } } }; //手机move function onTouchMove(point) { document.getElementById(user_id).style.left = (point.changedTouches[0].clientX) + "px"; document.getElementById(user_id).style.top = (point.changedTouches[0].clientY) + "px"; //告诉其他用户我的动作 let obj = { "room_id": room_id,//房间标识 "user_id": user_id,//用户标识 "say": "",//用户说话 "move": {//移动数据 "x": point.changedTouches[0].clientX, "y": point.changedTouches[0].clientY, "z": 0,//高度位移 "t": 0,//仰角大小(相对正北) "r": 0,//转角大小(相对正北) } }; msg.send(JSON.stringify(obj)); } document.getElementById(user_id).addEventListener("touchmove", onTouchMove, false); //电脑move function onMouseDown(point) { document.onmousemove = function (event) { document.getElementById(user_id).style.left = event.clientX + "px"; document.getElementById(user_id).style.top = event.clientY + "px"; //告诉其他用户我的动作 let obj = { "room_id": room_id,//房间标识 "user_id": user_id,//用户标识 "say": "",//用户说话 "move": {//移动数据 "x": event.clientX, "y": event.clientY, "z": 0,//高度位移 "t": 0,//仰角大小(相对正北) "r": 0,//转角大小(相对正北) } }; msg.send(JSON.stringify(obj)); }; document.onmouseup = function () { document.onmousemove = null; document.onmouseup = null; }; } document.getElementById(user_id).addEventListener("mousedown", onMouseDown, false); </script> </body> </html>
- GMP下载
- GMP入门