php安装swoole

  1. 作者QQ:67065435 QQ群:821635552

  2. 本站内容全部为作者原创,转载请注明出处!

  3. 下载swoole安装

    pecl install swoole
    
  4. 在php.ini添加swoole.so

    extension=swoole.so
    
  5. 聊天功能

  6. 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();
    
  7. 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();
    
  8. 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();
    
  9. 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);
    }
    
  10. 聊天功能,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>
    
  11. 游戏功能,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>
    
  12. 打开防火墙1234端口

    firewall-cmd --zone=public --add-port=1234/tcp --permanent
    systemctl restart firewalld
    
  13. 启动swoole服务

    php index.php
    
  14. 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);
    }
    
  15. 游戏功能,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>
    
  16. GMP首页

  17. GMP下载
  18. GMP入门
Copyright © 豆包嘿嘿~ 2012-∞ 冀ICP备17033181号 all right reserved,powered by Gitbook修订: 2020-12-23 03:55:29

results matching ""

    No results matching ""