威尼斯手机平台登陆-官方网站登录

威尼斯手机平台登陆为您带来世界三大博彩公司最新相关资讯,威尼斯官方网站登录充分考虑到不同地域网民的不同需求,威尼斯手机平台登陆良好的用户界面,人性化的操作,实用的功能设计使其广泛受到欢迎,推动实体出版、影视、动漫、游戏等相关文化产业的发展。

您的位置:威尼斯手机平台登陆 > 威尼斯登录首页 > 版本以后采用了这种数据结构之前用的是,下面要分享一段开启多进程的PHP代码

版本以后采用了这种数据结构之前用的是,下面要分享一段开启多进程的PHP代码

发布时间:2020-04-21 16:52编辑:威尼斯登录首页浏览(127)

    上边要分享一段开启多进度的PHP代码,相当的少做表达,都在讲解里面。

    正文实例陈说了php实现轻便的医生和医护人员进程创立、开启与关闭操作。分享给大家供大家参照他事他说加以考察,具体如下:

    描述

    正文实例汇报了PHP开启多进度的法子。分享给我们供大家参照他事他说加以考查。具体达成格局如下:

    前提要安装有pcntl扩大,可经过php -m查看是或不是安装

    前段时间在店肆布署crontab的时候,匪夷所思是还是不是足以用PHP去落到实处四个沙漏,颗粒度到秒级就好,因为crontab最多到分钟等级,同一时间也应用钻探了弹指间用PHP去落实的电火花计时器还真不太多,Swoole 扩大里面到贯彻了多少个飞秒级的沙漏很迅猛,但毕竟不是纯PHP代码写的,所以最终还是思考用PHP去完结贰个计时器类,以供就学参照他事他说加以考查。

    <?php 
     $IP='192.168.1.1';//Windows電腦的IP
     $Port='5900';        //VNC使用的Port
     $ServerPort='9999';//Linux Server對外使用的Port
     $RemoteSocket=false;//連線到VNC的Socket
     function SignalFunction($Signal){
      //這是主Process的訊息處理函數
     global $PID;//Child Process的PID
     switch ($Signal)
     {
      case SIGTRAP:
      case SIGTERM:
       //收到結束程式的Signal
       if($PID)
       {
        //送一個SIGTERM的訊號給Child告訴他趕快結束掉嘍
        posix_kill($PID,SIGTERM);
        //等待Child Process結束,避免zombie
        pcntl_wait($Status);
       }
       //關閉主Process開啟的Socket
       DestroySocket();
       exit(0); //結束主Process
       break;
      case SIGCHLD:
       /*
    當Child Process結束掉時,Child會送一個SIGCHLD訊號給Parrent
    當Parrent收到SIGCHLD,就知道Child Process已經結束嘍 ,該做一些
    結束的動作*/
       unset($PID); //將$PID清空,表示Child Process已經結束
       pcntl_wait($Status); //避免Zombie
       break;
      default:
     }
     }
     function ChildSignalFunction($Signal){
    //這是Child Process的訊息處理函數
     switch ($Signal)
     {
      case SIGTRAP:
      case SIGTERM:
    //Child Process收到結束的訊息
       DestroySocket(); //關閉Socket
       exit(0); //結束Child Process
      default:
     }
     }
     function ProcessSocket($ConnectedServerSocket){
     //Child Process Socket處理函數
     //$ConnectedServerSocket -> 外部連進來的Socket
     global $ServerSocket,$RemoteSocket,$IP,$Port;
     $ServerSocket=$ConnectedServerSocket;
     declare(ticks = 1); //這一行一定要加,不然沒辦法設定訊息處理函數。
    //設定訊息處理函數
     if(!pcntl_signal(SIGTERM, "ChildSignalFunction")) return;
     if(!pcntl_signal(SIGTRAP, "ChildSignalFunction")) return;
    //建立一個連線到VNC的Socket
     $RemoteSocket=socket_create(AF_INET, SOCK_STREAM,SOL_TCP);
    //連線到內部的VNC
     @$RemoteConnected=socket_connect($RemoteSocket,$IP,$Port);
     if(!$RemoteConnected) return; //無法連線到VNC 結束
    //將Socket的處理設為Nonblock,避免程式被Block住
     if(!socket_set_nonblock($RemoteSocket)) return;
     if(!socket_set_nonblock($ServerSocket)) return;
     while(true)
     {
    //這邊我們採用pooling的方式去取得資料
      $NoRecvData=false;   //這個變數用來判別外部的連線是否有讀到資料
      $NoRemoteRecvData=false;//這個變數用來判別VNC連線是否有讀到資料
      @$RecvData=socket_read($ServerSocket,4096,PHP_BINARY_READ);
    //從外部連線讀取4096 bytes的資料
      @$RemoteRecvData=socket_read($RemoteSocket,4096,PHP_BINARY_READ);
    //從vnc連線連線讀取4096 bytes的資料
      if($RemoteRecvData==='')
      {
    //VNC連線中斷,該結束嘍
       echo"Remote Connection Closen";
       return;   
      }
      if($RemoteRecvData===false)
      {
    /*
    由於我們是採用nonblobk模式
    這裡的情況就是vnc連線沒有可供讀取的資料
    */
       $NoRemoteRecvData=true;
    //清除掉Last Errror
       socket_clear_error($RemoteSocket);
      }
      if($RecvData==='')
      {
    //外部連線中斷,該結束嘍
       echo"Client Connection Closen";
       return;
      }
      if($RecvData===false)
      {
    /*
    由於我們是採用nonblobk模式
    這裡的情況就是外部連線沒有可供讀取的資料
    */
       $NoRecvData=true;
    //清除掉Last Errror
       socket_clear_error($ServerSocket);
      }
      if($NoRecvData&&$NoRemoteRecvData)
      {
    //如果外部連線以及VNC連線都沒有資料可以讀取時,
    //就讓程式睡個0.1秒,避免長期佔用CPU資源
       usleep(100000);
    //睡醒後,繼續作pooling的動作讀取socket
       continue;
      }
      //Recv Data
      if(!$NoRecvData)
      {
    //外部連線讀取到資料
       while(true)
       {
    //把外部連線讀到的資料,轉送到VNC連線上
        @$WriteLen=socket_write($RemoteSocket,$RecvData);
        if($WriteLen===false)
        {
    //由於網路傳輸的問題,目前暫時無法寫入資料
    //先睡個0.1秒再繼續嘗試。
         usleep(100000);
         continue;
        }
        if($WriteLen===0)
        {
    //遠端連線中斷,程式該結束了
         echo"Remote Write Connection Closen";
         return;
        }
    //從外部連線讀取的資料,已經完全送給VNC連線時,中斷這個迴圈。
        if($WriteLen==strlen($RecvData)) break;
    //如果資料一次送不完就得拆成好幾次傳送,直到所有的資料全部送出為止
        $RecvData=substr($RecvData,$WriteLen);
       }
      }
      if(!$NoRemoteRecvData)
      {
    //這邊是從VNC連線讀取到的資料,再轉送回外部的連線
    //原理跟上面差不多不再贅述
       while(true)
       {
        @$WriteLen=socket_write($ServerSocket,$RemoteRecvData);
        if($WriteLen===false)
        {
         usleep(100000);
         continue;
        }
        if($WriteLen===0)
        {
         echo"Remote Write Connection Closen";
         return;
        }
        if($WriteLen==strlen($RemoteRecvData)) break;
        $RemoteRecvData=substr($RemoteRecvData,$WriteLen);
       }
      }
     }
     }
     function DestroySocket(){
    //用來關閉已經開啟的Socket
     global$ServerSocket,$RemoteSocket;
     if($RemoteSocket)
     {
    //如果已經開啟VNC連線
    //在Close Socket前必須將Socket shutdown不然對方不知到你已經關閉連線了
      @socket_shutdown($RemoteSocket,2);
      socket_clear_error($RemoteSocket);
    //關閉Socket
      socket_close($RemoteSocket);   
     }
    //關閉外部的連線
     @socket_shutdown($ServerSocket,2);
     socket_clear_error($ServerSocket);
     socket_close($ServerSocket);
     }
    //這裡是整個程式的開頭,程式從這邊開始執行
    //這裡首先執行一次fork
     $PID=pcntl_fork();
     if($PID==-1) die("could not fork");
    //如果$PID不為0表示這是Parrent Process
    //$PID就是Child Process
    //這是Parrent Process 自己結束掉,讓Child成為一個Daemon。
     if($PID) die("Daemon PID:$PIDn");
    //從這邊開始,就是Daemon模式在執行了
    //將目前的Process跟終端機脫離成為daemon模式
     if(!posix_setsid()) die("could not detach from terminaln");
    //設定daemon 的訊息處理函數
     declare(ticks = 1);
     if(!pcntl_signal(SIGTERM, "SignalFunction")) die("Error!!!n");
     if(!pcntl_signal(SIGTRAP, "SignalFunction")) die("Error!!!n");
     if(!pcntl_signal(SIGCHLD, "SignalFunction")) die("Error!!!n");
    //建立外部連線的Socket
     $ServerSocket=socket_create(AF_INET, SOCK_STREAM,SOL_TCP);
    //設定外部連線監聽的IP以及Port,IP欄位設0,表示經聽所有介面的IP
     if(!socket_bind($ServerSocket,0,$ServerPort)) die("Cannot Bind Socket!n");
    //開始監聽Port
     if(!socket_listen($ServerSocket)) die("Cannot Listen!n");
    //將Socket設為nonblock模式
     if(!socket_set_nonblock($ServerSocket)) die("Cannot Set Server Socket to Block!n");
    //清空$PID變數,表示目前沒有任何的Child Process
     unset($PID);
     while(true)
     {
    //進入pooling模式,每隔1秒鐘就去檢查有沒有連線進來。
      sleep(1);
    //檢查有沒有連線進來
      @$ConnectedServerSocket=socket_accept($ServerSocket);
      if($ConnectedServerSocket!==false)
      {
    //有人連進來嘍
    //起始一個Child Process用來處理連線
       $PID=pcntl_fork();
       if($PID==-1) die("could not fork");
       if($PID) continue;//這是daemon process,繼續回去監聽。
       //這裡是Child Process開始
       //執行Socket裡函數
       ProcessSocket($ConnectedServerSocket);
      //處理完Socket後,結束掉Socket
       DestroySocket();
      //結束Child Process
       exit(0);
      }
     }
    
    pidfile = dirname.'/daemontest.pid'; } private function startDeamon() { if (file_exists { echo "The file $this->pidfile exists.n"; exit(); } $pid = pcntl_fork { die; } else if  { echo 'start ok'; exit; } else { // we are the child file_put_contents($this->pidfile, getmypid; } } private function start(){ $pid = $this->startDeamon { file_put_contents.'/test.txt', date, FILE_APPEND); sleep; } } private function stop(){ if (file_exists { $pid = file_get_contents; posix_kill; unlink; } } public function run { if { $this->start(); }else if { $this->stop(); }else{ echo 'param error'; } }}$deamon = new Daemon;
    
    php deamon.php start
    
    php deamon.php stop
    

    实现

    如上便是PHP开启多进度的主意,希望对您有着支持。

    更多关于PHP相关内容感兴趣的读者可查阅本站专项论题:《PHP进度与线程操作技艺总括》、《PHP互联网编制程序本领计算》、《PHP基本语法入门教程》、《PHP数组操作本领大全》、《php字符串用法计算》、《php+mysql数据库操作入门教程》及《php听而不闻数据库操作技艺汇总》

    在完结计时器代码的时候,用到了PHP系统自带的七个扩充

    期望本文所述对我们PHP程序设计具有助于。

    Pcntl - 多进度扩大 :

    关键就是让PHP能够而且张开超多子进度,并行的去管理部分职务。

    威尼斯登录首页,Spl - SplMinHeap - 小顶堆

    多个小顶堆数据布局,在促成电磁打点计时器的时候,选拔这种构造功效照旧不错的,插入、删除的日子复杂度都是O(logN卡塔尔国 ,像 libevent 的计时器也在 1.4 版本之后使用了这种数据构造早前用的是 rbtree,假使假定使用链表恐怕固定的数组,每一次插入、删除恐怕都急需重新遍历大概排序,照旧有一定的性能难点的。

    流程

    威尼斯登录首页 1

    说明

    1、定义电火花计时器构造,有啥参数之类的.
    2、然后全数注册进我们的电火花计时器类 Timer.
     3、调用放大计时器类的monitor方法,早先开展监听.
    4、监听进度正是二个while死循环,不断的去看时间堆的堆顶是还是不是到期了,本来寻思每秒循环看一遍,后来一想每秒循环看二遍依旧多少难点,假使赶巧在我们sleep(1State of Qatar的时候电火花计时器有到期的了,那我们就不可能立刻去精准实行,可能会有延时的风险,所以依然选用usleep(1000卡塔尔国 飞秒级的去看还要也能够将经过挂起缓和 CPU 负载.

    代码

     /***
     * Class Timer
     */
     class Timer extends SplMinHeap
     {
       /**
       * 比较根节点和新插入节点大小
       * @param mixed $value1
       * @param mixed $value2
       * @return int
       */
       protected function compare($value1, $value2)
       {
         if ($value1['timeout'] > $value2['timeout']) {
           return -1;
         }
         if ($value1['timeout'] < $value2['timeout']) {
           return 1;
         }
         return 0;
       }
       /**
       * 插入节点
       * @param mixed $value
       */
       public function insert($value)
       {
         $value['timeout'] = time() + $value['expire'];
         parent::insert($value);
       }
       /**
       * 监听
       * @param bool $debug
       */
       public function monitor($debug = false)
       {
         while (!$this->isEmpty()) {
           $this->exec($debug);
           usleep(1000);
         }
       }
       /**
       * 执行
       * @param $debug
       */
       private function exec($debug)
       {
         $hit = 0;
         $t1  = microtime(true);
         while (!$this->isEmpty()) {
           $node = $this->top();
           if ($node['timeout'] <= time()) {
             //出堆或入堆
             $node['repeat'] ? $this->insert($this->extract()) : $this->extract();
             $hit = 1;
             //开启子进程
             if (pcntl_fork() == 0) {
               empty($node['action']) ? '' : call_user_func($node['action']);
               exit(0);
             }
             //忽略子进程,子进程退出由系统回收
             pcntl_signal(SIGCLD, SIG_IGN);
           } else {
             break;
           }
         }
         $t2 = microtime(true);
         echo ($debug && $hit) ? '时间堆 - 调整耗时: ' . round($t2 - $t1, 3) . "秒rn" : '';
       }
     }
    

    实例

    $timer = new Timer();
    //注册 - 3s - 重复触发
    $timer->insert(array('expire' => 3, 'repeat' => true, 'action' => function(){
      echo '3秒 - 重复 - hello world' . "rn";
    }));
    //注册 - 3s - 重复触发
    $timer->insert(array('expire' => 3, 'repeat' => true, 'action' => function(){
      echo '3秒 - 重复 - gogo' . "rn";
    }));
    //注册 - 6s - 触发一次
    $timer->insert(array('expire' => 6, 'repeat' => false, 'action' => function(){
      echo '6秒 - 一次 - hello xxxx' . "rn";
    }));
    //监听
    $timer->monitor(false);
    

    推行结果

    威尼斯登录首页 2

    也测量试验过比较极端的图景,同时1000个放大计时器1s全副届期,时间堆全部调动完仅需 0.126s 那是没难点的,然则每调度完三个放大计时器就供给去开启多个子进度,那块或者比较耗费时间了,有希望1s管理不完那1000个,就能影响后一次监听继续接触,然则不开启子进度,譬喻直接施行相应还是能够拍卖完的。。。。当然肯定有越来越好的方式,近来一定要想到这么。

    本文由威尼斯手机平台登陆发布于威尼斯登录首页,转载请注明出处:版本以后采用了这种数据结构之前用的是,下面要分享一段开启多进程的PHP代码

    关键词:

上一篇:选择排序法

下一篇:没有了