swoole学习笔记之多线程端口监听问题记录多进程epoll模式

编程

epoll模式 主要就是直接对socket进行监听,不需要轮询,如果socket有状态变化就会触发

<?php

class Worker{

    //监听socket

    protected $socket = NULL;

    //连接事件回调

    public $onConnect = NULL;

    public  $reusePort=1;

    //接收消息事件回调

    public $onMessage = NULL;

    public $workerNum=2; //子进程个数

    public  $allSocket; //存放所有socket

    public  $addr;

    public function __construct($socket_address) {

        //监听地址+端口

        $this->addr=$socket_address;

    }

    public function start() {

        //获取配置文件

        $this->fork();

    }

    public function fork(){

        for ($i=0;$i<$this->workerNum;$i++){

            $pid=pcntl_fork(); //创建成功会返回子进程id

            if($pid<0){

                exit("创建失败");

            }else if($pid>0){

                //父进程空间,返回子进程id

            }else{ //返回为0子进程空间

echo "zi";

                $this->accept();//子进程负责接收客户端请求

                exit;//为什么这里exit退出后子进程不退出?这里应该时阻止继续运行,然后经常在监听,所以没有退出

            }

        }

        exit;//这里如果exit,主进程就会退出来,导致下面结束子进程的代码失效

        //放在父进程空间,结束的子进程信息,阻塞状态

        $status=0;

        for ($i=0;$i<$this->workerNum;$i++) {

            $pid = pcntl_wait($status);

        }

    }

    public  function  accept(){

        $opts = array(

            "socket" => array(

                "backlog" =>10240, //成功建立socket连接的等待个数

            ),

        );

//创建资源流上下文

      $context = stream_context_create($opts);

      //开启多端口监听,并且实现负载均衡

//stream_context_set_option 设置资源流

// 参数 $stream_or_context, $wrapper, $option, $value

//$stream_or_context 资源流上下文

//$wrapper,包装器(wrapper),包括 http,socket,ssl等

//$option 设置的选项(不确定)

//$value 选项对应的值

     

//设置端口可以多个监听,开启监听端口复用后允许多个无亲缘关系的进程监听相同的端口,并且由系统内核做负载均衡,

//决定将socket连接交给哪个进程处理,避免了惊群效应,

//可以提升多进程短连接应用的性能。

    stream_context_set_option($context,"socket","so_reuseport",1);

      stream_context_set_option($context,"socket","so_reuseaddr",1);

      $this->socket=stream_socket_server($this->addr,$errno,$errstr,STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,$context);

        //第一个需要监听的事件(服务端socket的事件),一旦监听到可读事件之后会触发

        //异步监听

        swoole_event_add($this->socket,function ($fd){

                $clientSocket=stream_socket_accept($fd);

                //触发事件的连接的回调

                if(!empty($clientSocket) && is_callable($this->onConnect)){

echo "连接事件触发",(int)$clientSocket,PHP_EOL;

                    call_user_func($this->onConnect,$clientSocket);

                }

            //监听客户端可读

             swoole_event_add($clientSocket,function ($fd){

                //从连接当中读取客户端的内容

                $buffer=fread($fd,1024);

                //如果数据为空,或者为false,不是资源类型

                if(empty($buffer)){

                    if(!is_resource($fd) || feof($fd) ){

                        //触发关闭事件

                        fclose($fd);

                    }

                }

                //正常读取到数据,触发消息接收事件,响应内容

                if(!empty($buffer) && is_callable($this->onMessage)){

                    call_user_func($this->onMessage,$fd,$buffer);

                }

            });

        });

    }

}

$worker = new Worker("tcp://0.0.0.0:9801");

//开启多进程的端口监听

$worker->reusePort = true;

//连接事件

$worker->onConnect = function ($fd) {

    echo "连接事件触发",(int)$fd,PHP_EOL;

};

//消息接收

$worker->onMessage = function ($conn, $message) {

    var_dump("123");

    $content="123123123";

    $http_resonse = "HTTP/1.1 200 OK

";

    $http_resonse .= "Content-Type: text/html;charset=UTF-8

";

    $http_resonse .= "Connection: keep-alive

"; //连接保持

    $http_resonse .= "Server: php socket server

";

    $http_resonse .= "Content-length: ".strlen($content)."

";

    $http_resonse .= $content;

    fwrite($conn, $http_resonse);

};

$worker->start(); //启动

以上是 swoole学习笔记之多线程端口监听问题记录多进程epoll模式 的全部内容, 来源链接: utcz.com/z/512094.html

回到顶部