zoukankan      html  css  js  c++  java
  • socket + pcntl_fork 实现客户端请求,服务器实时监听返回处理 消息推送

    <?php
        /*
            socket链接整个过程
            1,socket_create
            第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置AF_INET;
            第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM、原始套接字SOCK_RAW(WinSock接口并不适用某种特定的协议去封装它,而是由程序自行处理数据包以及协议首部);
            第三个参数指定应用程序所使用的通信协议。此参数可以指定单个协议系列中的不同传输协议。在Internet通讯域中,此参数一般取值为0,系统会根据套接字的类型决定应使用的传输层协议。
            2,socket_connect
            3,socket_write
            4,socket_read
            5,socket_close
        */
        Class Client {
            static private $socket = null;
    
            public function __construct() {
                //不报错
                error_reporting(0);
                //引入数据库
                require_once('conn.php');
                if(self::$socket == null) 
                    self::$socket = socket_create(AF_INET,SOCK_STREAM,0);
                if(self::$socket === false)
                    exit('create socket fail! please check it!' . $this->err());
            }
    
            //连接并发送数据
            public function conn($ip,$port,$data) {
                //数组数据序列号保存发送
                $data = serialize($data);
                if(!socket_connect(self::$socket,$ip,$port))
                    exit('socket connect error!' . $this->err());
                if(socket_write(self::$socket,$data) === false)
                    exit('socket write error!' . $this->err());
            }
    
            //获取数据
            public function getBack() {
                $res = socket_read(self::$socket,4096);
                if($res === false)
                    exit('socket read error !' . $this->err());
                if($res)
                    return $res;
                else 
                    return 'nothing return';
            }
    
            //析构释放资源
            public function __destruct() {
                socket_close(self::$socket);
            }
    
            //错误
            private function err() {
                return socket_strerror(socket_last_error());
            }
        }
    <?php
        /*
            socket 服务器通信整个过程
            socket_creat
            socket_bind
            socket_listen
            socket_accetp
            socket_read
            socket_write
            socket_close
    
            注:1,服务器需要开启php 的pcntl系列扩展,
                2,服务器必须开通对应端口,而且需跟客户端请求端口一致
        */
        //监听客户端触发,
        class Message {
            private $socket     = null;
    
            public function __construct($info) {
                $this->init($info);
                //子程序结束后,系统自动回收,避免产生僵尸进程
                pcntl_signal(SIGCLD, SIG_IGN);
                pcntl_signal(SIGCHLD,SIG_IGN);
                //dojob
                $this->doJob();
            }
    
            //初始化
            private function init($info) {
                //创建通信
                if(!$this->socket = socket_create(AF_INET,SOCK_STREAM,0)) 
                    exit('error: create fail!' . $this->err());
                //绑定端口
                if(!socket_bind($this->socket,$info['ip'],$info['port']))
                    exit('error: bind fail' . $this->err());
                //监听端口
                if(!socket_listen($this->socket))
                    exit('error: listen fail' . $this->err());
            }
    
            //处理数据
            public function doJob() {
                do{
                    //接受一个通信
                    $mes_sock     = socket_accept($this->socket);
                    if($mes_sock === false)
                        exit('error: accept fail!' . $this->err());
    
                    //读取到客户端传送过来的数据
                    $mes_client = socket_read($mes_sock,4096);
                    if($mes_client === false)
                        exit('error: read fail' . $this->err());
                    $data         = unserialize($mes_client);
    
                    //开始分进程
                    $pid         = pcntl_fork();
                    if($pid) {
    
                        //父进程
                        $remeg             = '';
                        if($data['type'] == 1) 
                            $remeg         = 'request ok!';
                        else 
                            $remeg         = 'allow ok!';
    
                        //将消息返回
                        if(socket_write($mes_sock,$remeg) === false)
                            exit('error: write fail' . $this->err());
                    }else {
                        require_once('Db.class.php');
                        $conn             = Db::getInstance(array('ip'=>'192.168.1.11','user'=>'root','pass'=>'123456','database'=>'test'));
                        //子进程
                        if($data['type'] == 1) {
                            //处理用户申请加入圈子,当消息发送成功后,更改数据库信息
                            echo "处理用户申请加入圈子
    ";
                            //$sql ="UPDATE test_add SET status = 1 WHERE status  ";
                            die;
                        }else{
                            //处理圈主审核
                            echo "处理圈主审核
    ";
                            die;
                        }
                    }
    
                    //释放资源
                    socket_close($mes_sock);
                }while(1);
            }
    
    
            //错误
            private function err() {
                return socket_strerror(socket_last_error());
            }
    
            //析构释放
            public function __desctruct() {
                socket_close($this->socket);
            }
        }
    
        //运行
        $message     = new Message(array('ip'=>'192.168.1.6','port'=>'1935'));

    //附属的db类

    <?php
        /*
            数据库类
        */
        class Db {
            //用于存放实例化的对象
            static private $_instance = null;
    
            //公共静态方法获取实例化的对象
            static protected function getInstance($data) {
                if (!(self::$_instance instanceof self)) {
                    self::$_instance = new self($data);
                }
                return self::$_instance;
            }
            
            //私有克隆
            private function __clone() {}
            
            //私有构造
            private function __construct($data) {
                $conn             = mysql_connect($data['ip'],$data['user'],$data['pass']);
                if(!$conn)
                    exit('数据库连接错误!' . mysql_error());
                mysql_query('set names utf8');
                mysql_query('use '. $data['database']);
            }
    
        }

    可以实现客户端请求后,服务器立马返回数据,通知客户端请求成功。再子进程处理。而且不会有defunct僵尸进程。

  • 相关阅读:
    @ControllerAdvice + @ExceptionHandler 使用
    将博客搬至CSDN
    Docker pull网络错误
    Centos7.5安装Docker
    Oracle18c创建不带C##的用户
    Centos7.5静默安装Oracle18c
    nodeJs和JavaScript的异同
    maven项目引入本地包,不使用中央仓库
    java中把指数形式的数字转为正常形式显示
    validateJarFile jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
  • 原文地址:https://www.cnblogs.com/lxdd/p/3895472.html
Copyright © 2011-2022 走看看