首页 > 代码库 > socket + pcntl_fork 实现客户端请求,服务器实时监听返回处理 消息推送

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 "处理用户申请加入圈子\n";                        //$sql ="UPDATE test_add SET status = 1 WHERE status  ";                        die;                    }else{                        //处理圈主审核                        echo "处理圈主审核\n";                        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僵尸进程。