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

目录
相关文章
|
10天前
|
自然语言处理 编译器 应用服务中间件
PHP在服务器上的运行过程
PHP在服务器上的运行过程
29 7
|
8天前
|
监控 PHP Apache
优化 PHP-FPM 参数配置:实现服务器性能提升
优化PHP-FPM的参数配置可以显著提高服务器的性能和稳定性。通过合理设置 `pm.max_children`、`pm.start_servers`、`pm.min_spare_servers`、`pm.max_spare_servers`和 `pm.max_requests`等参数,并结合监控和调优措施,可以有效应对高并发和负载波动,确保Web应用程序的高效运行。希望本文提供的优化建议和配置示例能够帮助您实现服务器性能的提升。
24 3
|
1月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
138 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
1月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
147 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
23天前
|
PHP 开发者
PHP作为一门流行的服务器端脚本语言,深入理解PHP的命名空间
【10月更文挑战第22天】PHP作为一门流行的服务器端脚本语言,自1995年诞生以来,已经发展了二十多年。在这二十多年的时间里,PHP经历了多次重大版本的更新,不断增加新特性和改进。其中,命名空间(Namespace)是PHP 5.3.0引入的一个重要特性,它为PHP的代码组织和重用提供了一种新的方式。本文将从三个部分深入理解PHP的命名空间:一是命名空间的基本概念和作用;二是PHP命名空间的使用方法;三是通过实例讲解命名空间的应用。
25 4
|
安全 关系型数据库 MySQL
阿里云服务器配置windows2003+iis6+php+ftp+mysql+zend教程
阿里云服务器ECS可选的操作系统中,已经不见了Windows 2003操作系统,但很多用户特别是配置低的低端用户,仍然需要windows2003系统。如果你属于这种情况,请在购买服务器时联系阿里云授权合作伙伴万维景盛,我司特意为用户保留了2003系统的64位和32位版
3922 0
|
2月前
|
安全 关系型数据库 MySQL
PHP与MySQL交互:从入门到实践
【9月更文挑战第20天】在数字时代的浪潮中,掌握PHP与MySQL的互动成为了开发动态网站和应用程序的关键。本文将通过简明的语言和实例,引导你理解PHP如何与MySQL数据库进行对话,开启你的编程之旅。我们将从连接数据库开始,逐步深入到执行查询、处理结果,以及应对常见的挑战。无论你是初学者还是希望提升技能的开发者,这篇文章都将为你提供实用的知识和技巧。让我们一起探索PHP与MySQL交互的世界,解锁数据的力量!
|
2月前
|
NoSQL 关系型数据库 MySQL
不是 PHP 不行了,而是 MySQL 数据库扛不住啊
【9月更文挑战第8天】这段内容讨论了MySQL在某些场景下面临的挑战及其原因,并指出这些问题不能完全归咎于MySQL本身。高并发读写压力、数据量增长以及复杂查询和事务处理都可能导致性能瓶颈。然而,应用程序设计不合理、系统架构不佳以及其他数据库选择和优化策略不足也是重要因素。综合考虑这些方面才能有效解决性能问题,而MySQL通过不断改进和优化,仍然是许多应用场景中的可靠选择。
138 9
|
3月前
|
存储 SQL 关系型数据库
PHP与MySQL交互的奥秘
【8月更文挑战第29天】在编程的世界里,PHP和MySQL就像是一对默契的舞伴,共同演绎着数据的交响曲。本文将带你探索它们之间的互动,从连接数据库到执行查询,再到处理结果,每一步都充满了节奏与和谐。我们将一起走进这段代码的旅程,感受数据流动的魅力。
|
9天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
24 1