zoukankan      html  css  js  c++  java
  • swoole(4)网络服务模型(多进程master-worker模型)

    一:select 与epoll

    select:监听并等待多个文件描述符的属性变化(可读、可写、错误异常),调用后select会阻塞,直到有描述符就绪,函数才返回,通过便利fdset,来找到就绪的描述符,并且最大描述符不能超过1024

    epoll:相对select来说,更灵活,没有描述符限制,无需轮训,epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个时间表中(当连接有io流事件产生的时候,epoll就会告诉进程有io流事件产生,然后进程就去处理)

    代码:(使用swoole中的event事件)

    <?php
    
    class Worker {
        //监听socket
        protected $socket = NULL;
        //连接事件回调
        public $onConnect = NULL;
        //接收消息事件回调
        public $onMessage = NULL;
        public $workerNum = 10;
    
        public function __construct($socket_address) {
            $this->socket = stream_socket_server($socket_address);
        }
    
        //创建子进程
        public function fork() {
            $this->accept();
        }
    
        public function accept() {
            swoole_event_add($this->socket,function ($fd){
                //服务端接收客户端请求
                $clientSocket = stream_socket_accept($this->socket);
                if (!empty($clientSocket) && is_callable($this->onConnect)) {
                    call_user_func($this->onConnect, $clientSocket);
                }
                swoole_event_add($clientSocket,function ($fd){
                    $buffer = fread($fd, 65535);
                    //如果数据为空,或者为false,不是资源类型
                    if(empty($buffer)){
                        if(feof($fd) || !is_resource($fd)){
                            //触发关闭事件
                            fclose($fd);
                        }
                    }
                    if (!empty($buffer) && is_callable($this->onMessage)) {
                        call_user_func($this->onMessage, $fd, $buffer);
                    }
                });
            });
            echo '非阻塞';
        }
    
        public function start() {
            $this->fork();
        }
    }
    
    
    $worker = new Worker('tcp://0.0.0.0:9801');
    
    $worker->onConnect = function ($args) {
        echo "新的连接来了.{$args}.PHP_EOL";
    };
    $worker->onMessage = function ($conn, $message) {
    //    var_dump($conn, $message);
        $content = "hello word qwe";
        $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();

    二:多进程master-worker模型

    流程设计:

    1. master进程,负责处理配置文件读取,启动,终止和维护worker进程数,当worker进程推出后,会自动重新启动新的worker
    2. worker进程的主要任务就是完成具体的逻辑(监听端口、接受请求、使用epoll绝收请求,执行业务逻辑关闭连接)

    代码:

    <?php
    
    class Worker {
        //监听socket
        protected $socket = NULL;
        //连接事件回调
        public $onConnect = NULL;
        //接收消息事件回调
        public $onMessage = NULL;
        public $workerNum = 4;
        public $addr;
    
        public function __construct($socket_address) {
           $this->addr=$socket_address;
        }
    
        //创建子进程
        public function fork() {
            for ($i = 0; $i < $this->workerNum; $i++) {
                $pid = pcntl_fork();
                if ($pid < 0) {
                    exit('创建失败');
                } else if ($pid > 0) {
    
                } else {
                    $this->accept();
                    exit();
                }
            }
            $status = 0;
            //回收子进程
            for ($i = 0; $i < $this->workerNum; $i++) {
                $pid = pcntl_wait($status);
            }
        }
    
        public function accept() {
            $opts = array(
                'socket' => array(
                    'backlog' => '10240',
                ),
            );
    
            $context = stream_context_create($opts);
    
            stream_context_set_option($context,'socket','so_reuseport',1);
    
            $this->socket = stream_socket_server($this->addr,$error,$errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,$context);
            swoole_event_add($this->socket, function ($fd) {
                //服务端接收客户端请求
                $clientSocket = stream_socket_accept($this->socket);
                if (!empty($clientSocket) && is_callable($this->onConnect)) {
                    call_user_func($this->onConnect, $clientSocket);
                }
                swoole_event_add($clientSocket, function ($fd) {
                    $buffer = fread($fd, 65535);
                    //如果数据为空,或者为false,不是资源类型
                    if (empty($buffer)) {
                        if (feof($fd) || !is_resource($fd)) {
                            //触发关闭事件
                            fclose($fd);
                        }
                    }
                    if (!empty($buffer) && is_callable($this->onMessage)) {
                        call_user_func($this->onMessage, $fd, $buffer);
                    }
                });
            });
            echo '非阻塞';
        }
    
        public function start() {
            $this->fork();
        }
    }
    
    
    $worker = new Worker('tcp://0.0.0.0:9801');
    
    $worker->onConnect = function ($args) {
        echo "新的连接来了.{$args}.PHP_EOL";
    };
    $worker->onMessage = function ($conn, $message) {
    //    var_dump($conn, $message);
        $content = "hello word qwe";
        $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();
  • 相关阅读:
    占德国与哥斯达黎加
    晕,终于见识到了J2me的代码容量限制
    使用Adobe Acrobat SDK 需注意的要点
    看到一窝火的对联
    Entity Framework 学习初级篇4Entity SQL(转)
    Entity Framework 学习初级篇6EntityClient(转)
    ASP.NET MVC3 快速入门第三节 添加一个视图(转)
    ASP.NET MVC3 快速入门第一节 概述(转)
    Entity Framework 学习初级篇1EF基本概况(转)
    PB TreeView 查找节点(转)
  • 原文地址:https://www.cnblogs.com/8013-cmf/p/12410579.html
Copyright © 2011-2022 走看看