php实现多进程socket服务器class

简介: php实现多进程socket服务器class

该类实现了多进程的socket服务,目前只写了关于TCP协议,待完善其他内容

所需扩展:socket  pcntl

<?php
/**
 * Created by PhpStorm.
 * User: tioncico
 * Date: 18-5-1
 * Time: 下午7:56
 */
class SphpSocket
{
    private static $_instance;
    public $connect_list = array();//客户端列表
    public $connect_callback, $receive_callback, $close_callback;//回调函数
    public $server;//socket服务
    public $is_run=true;//是否运行
    public $config = array(//各种配置
        'debug'=>true,
        'host' => '0.0.0.0',
        'port' => '9501',
        'domain'   => AF_INET,
        'type'     => SOCK_STREAM,
        'protocol' => SOL_TCP,
        'accept' => 511,
        'option_level' => SOL_SOCKET,
        'optname'      => SO_REUSEADDR,
        'optval'       => 1,
        'read_length'=>1024,
        'read_type'=>PHP_NORMAL_READ
    );
    public $error_log=array();
    public static function getInstance($host, $port)
    {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new static($host, $port);
        }
        return self::$_instance;
    }
    public function __construct($host, $port)
    {
        $this->config['host'] = $host;
        $this->config['port'] = $port;
    }
    /**
     * 绑定事件
     * @param $type connect|receive|close
     * @param callable $function
     */
    public function on($type, callable $function)
    {
        switch (strtolower($type)) {
            case 'connect':
                $this->connect_callback = $function;
                break;
            case 'receive':
                $this->receive_callback = $function;
                break;
            case 'close':
                $this->close_callback = $function;
                break;
        }
        return $this;
    }
    public function onConnect($connection){
        if (is_callable($this->connect_callback)) {
            call_user_func($this->connect_callback,$connection);
        }
    }
    public function onReceive($connection,$data){
        if (is_callable($this->receive_callback)) {
            call_user_func($this->receive_callback,$connection,$data);
        }
    }
    public function onClose($connection){
        if (is_callable($this->close_callback)) {
            call_user_func($this->close_callback,$connection);
        }
    }
    /**
     *
     */
    public function start()
    {
        $this->createSocket();
        echo '创建socket成功!'.PHP_EOL;
        $this->bindSocket();
        echo '绑定端口成功!'.PHP_EOL;
        $this->listenSocket();
        echo '监听端口成功!'.PHP_EOL;
        $this->setOptionSocket();
        $this->acceptSocket();
        return $this;
    }
    /**
     * 创建socket
     * @return $this
     * @throws Exception
     */
    protected function createSocket()
    {
        $this->server = socket_create($this->config['domain'], $this->config['type'], $this->config['protocol']);
        if ($this->server === false) {
            throw new Exception('创建socket失败!');
        }
        return $this;
    }
    /**
     * 绑定端口
     * @return $this
     * @throws Exception
     */
    protected function bindSocket()
    {
        $this->server === false && $this->createSocket();
        $result = socket_bind($this->server, $this->config['host'], $this->config['port']);
        if ($result === false) {
            throw new Exception('绑定端口失败!');
        }
        return $this;
    }
    /**
     * 监听端口
     * @param null $accept
     * @return $this
     * @throws Exception
     */
    protected function listenSocket($accept = null)
    {
        $this->server === false && $this->createSocket();
        $accept || $accept = $this->config['accept'];
        $result = socket_listen($this->server, $accept);
        if ($result === false) {
            throw new Exception('监听端口失败!');
        }
        return $this;
    }
    /**
     * 配置socket
     * @return $this
     * @throws Exception
     */
    protected function setOptionSocket()
    {
        $this->server === false && $this->createSocket();
        $result = socket_set_option($this->server, $this->config['option_level'], $this->config['optname'], $this->config['optval']);
        if ($result === false) {
            throw new Exception('配置socket失败!');
        }
        return $this;
    }
    /**
     * 接收socket连接
     */
    protected function acceptSocket(){
        $this->server === false && $this->createSocket();
        while(true&&$this->is_run===true){
            $connection = socket_accept($this->server);
            if($connection===false){
            }else{
                $this->addConnectionList($connection);
                $this->onConnect($connection);
                $this->forkProcess($connection);
            }
        }
    }
    /**
     * 写入客户端信息
     * @param $connection
     * @return $this
     */
    protected function addConnectionList($connection){
//        $fd =
        $this->connect_list[(string)$connection]['fd']=$connection;
        return $this;
    }
    /**
     * 写入客户端进程id
     * @param $connection
     * @param $pid
     * @return $this
     */
    protected function addConnectionListProcess($connection,$pid){
        $this->connect_list[(string)$connection]['pid']=$pid;
        return $this;
    }
    /**
     * 派生进程处理
     * @param $connection
     */
    protected function forkProcess($connection){
        $pid = pcntl_fork();
        if($pid>0){//使用主进程处理客户端其他请求,子进程继续监听连接请求
            $this->addConnectionListProcess($connection,$pid);
            $this->readSocket($connection);
        }else{
        }
    }
    /**
     * 读取socket信息
     * @param $connection
     */
    protected function readSocket($connection){
        while(true&&isset($this->connect_list[(string)$connection])&&$this->is_run){
            $data = @socket_read($connection,$this->config['read_length'],$this->config['read_type']);
            if($data===false){
                $this->close($connection);
            }else{
                $this->onReceive($connection,$data);
            }
        }
   }
    /**
     * 发送消息给客户端
     * @param $connection
     * @param $msg
     * @return int
     */
   public function send($connection,$msg){
       $result = socket_write($connection, $msg,strlen($msg));
       return $result;
   }
    /**
     * 主动关闭客户端
     * @param $connection
     */
   public function close($connection){
       $this->onClose($connection);
       //先关掉子进程
       posix_kill($this->connect_list[(string)$connection]['pid'],SIGTERM);
       $result = socket_close($connection);
       unset($this->connect_list[(string)$connection]);
       return $result;
   }
}

开启例子:

$socket= SphpSocket::getInstance('0.0.0.0',9501);

$socket->on('connect',function($connection)use($socket){

    $socket->send($connection,'恭喜您连接成功!');

});

$socket->on('receive',function($connection,$data)use($socket){

    $result$socket->send($connection,'您发送的消息是:'.$data);

    var_dump($data);

    if(trim($data)=='关闭'){

        $socket->close($connection);

    }

    echo"发送消息成功";

 

});

$socket->on('close',function($connection)use($socket){

    var_dump($connection.'已经关闭连接');

});

$socket->start();

image.png

目录
相关文章
|
数据库
【YashanDB知识库】服务器重启后启动yasom和yasagent进程时有告警
【YashanDB知识库】服务器重启后启动yasom和yasagent进程时有告警
|
数据库
【YashanDB知识库】服务器重启后启动yasom和yasagent进程时有告警
本文介绍了YashanDB在特定场景下的问题分析与解决方法。当使用yasboot重启数据库后,yasom和yasagent进程虽启动成功但出现告警,原因是缺少libnsl.so.1库文件或环境变量配置错误。解决步骤包括:检查系统中是否存在该库文件,若不存在则根据操作系统类型安装(有外网时通过yum或apt,无外网时创建符号链接),若存在则调整环境变量配置,并重新启动相关进程验证问题是否解决。
|
应用服务中间件 PHP nginx
当你的nginx服务器和php服务器不在一起的时候,这个nginx 的root目录问题
两个服务器的网站代码目录需要对齐,docker容器里面也是一样
|
自然语言处理 编译器 应用服务中间件
PHP在服务器上的运行过程
PHP在服务器上的运行过程
430 7
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
477 3
|
监控 PHP Apache
优化 PHP-FPM 参数配置:实现服务器性能提升
优化PHP-FPM的参数配置可以显著提高服务器的性能和稳定性。通过合理设置 `pm.max_children`、`pm.start_servers`、`pm.min_spare_servers`、`pm.max_spare_servers`和 `pm.max_requests`等参数,并结合监控和调优措施,可以有效应对高并发和负载波动,确保Web应用程序的高效运行。希望本文提供的优化建议和配置示例能够帮助您实现服务器性能的提升。
1331 3
|
PHP Windows 索引
优雅的玩PHP多进程
proc_open (PHP 4 >= 4.3.0, PHP 5, PHP 7) proc_open — 执行一个命令,并且打开用来输入/输出的文件指针。 说明 ¶ resource proc_open ( string $cmd , array $descriptorspec , array &$pipes [, string$cwd [, array $env [, array $other_options ]]] ) 类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力。
1816 0
|
12月前
|
关系型数据库 MySQL PHP
PHP和Mysql前后端交互效果实现
本文介绍了使用PHP连接MySQL数据库的基本函数及其实现案例。内容涵盖数据库连接、选择数据库、执行查询、获取结果等常用操作,并通过用户登录和修改密码的功能实例,展示了PHP与MySQL的交互过程及代码实现。
557 0
PHP和Mysql前后端交互效果实现
|
关系型数据库 MySQL Linux
查看Linux、Apache、MySQL、PHP版本的技巧
以上就是查看Linux、Apache、MySQL、PHP版本信息的方法。希望这些信息能帮助你更好地理解和使用你的LAMP技术栈。
735 17
|
关系型数据库 MySQL PHP
源码编译安装LAMP(HTTP服务,MYSQL ,PHP,以及bbs论坛)
通过以上步骤,你可以成功地在一台Linux服务器上从源码编译并安装LAMP环境,并配置一个BBS论坛(Discuz!)。这些步骤涵盖了从安装依赖、下载源代码、配置编译到安装完成的所有细节。每个命令的解释确保了过程的透明度,使即使是非专业人士也能够理解整个流程。
559 18

热门文章

最新文章