php安装swoole

  1. 文档地址
  2. 韩天峰blog
  3. 阮一峰非PHP方案

  4. 安装前的准备

     yum install \
     git \
     gcc \
     gcc-c++ \
     wget \
     make \
     automake \
     autoconf \
     pcre-devel \
     -y \
     # 如果启用async-redis (--enable-async-redis)
     git clone https://github.com/redis/hiredis.git
     cd ./hiredis
     make
     make install
     # 如果启用http2 (--enable-http2)
     wget https://github.com/nghttp2/nghttp2/releases/download/v1.25.0/nghttp2-1.25.0.tar.gz
     tar -zxvf nghttp2-1.25.0.tar.gz
     cd nghttp2-1.25.0
     ./configure
     make
     make install
    
  5. 下载swoole安装 参考链接 编译参数

     wget http://pecl.php.net/get/swoole-1.9.1.tgz
     tar -zxvf swoole-1.9.1.tgz
     cd swoole-1.9.1
     phpize
    
     ./configure \
    
     make
     make install
    
  6. 在php.ini添加swoole.so

     extension=swoole.so
    
  7. 聊天功能

  8. PHP原生写法

    <?php
    function on_open(swoole_websocket_server $server, $request)
    {
       //客户端已经连接
    }
    function on_close($server, $fd)
    {
       //客户端已经断开
    }
    function on_message(swoole_websocket_server $server, $request)
    {
        $data = $request->data;
        foreach ($server->connections as $fd) {
            //消息发送者客户端id:$request->fd
            //消息接收者客户端id:$fd
            $server->push($fd, $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();
    
  9. 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, $request) {
        $data = $request->data;
        foreach ($server->connections as $fd) {
            $server->push($fd, $data);
        }
    });
    $server->start();
    
  10. 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();
    
  11. PHP守护进程写法(支持ssl安全传输,支持守护进程启动)

    #!/usr/local/php7/bin/php
    <?php
    //处理传入参数
    $opt = getopt('', ["port::", "address::", "ssl::", "cert::", "key::", "daemon::"]);
    $opt = [
        'port' => !empty($opt['port']) ? $opt['port'] : (isset($opt['ssl']) ? 443 : 80),
        'address' => !empty($opt['address']) ? $opt['address'] : '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['address'], $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['address'], $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, $request) {
        //客户端发来消息
        $data = $request->data;
        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, $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();
    }
    
  12. 聊天功能,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>
    
  13. 游戏功能,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>
    
  14. 打开防火墙1234端口

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

     php index.php
    
  16. 官方文档

results matching ""

    No results matching ""