【问题标题】:Memory leaks in socket server PHP套接字服务器 PHP 中的内存泄漏
【发布时间】:2015-11-30 09:48:19
【问题描述】:
Class ServerSocket {

    protected $IP_ADDRESS = IP_ADDRESS; 
    protected $PORT = PORT_NUMBER; 
    protected $userClass = 'WebSocketUser'; 
    protected $mysock;
    protected $users = array();
    public static $sockets = array();
    public $clients = array();
    protected $countSockets = 0;
    protected $socketsLimit = 1000;

    FUNCTION __construct()
    {
        $this->mysock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        socket_bind($this->mysock, $this->IP_ADDRESS, $this->PORT);
        socket_listen($this->mysock, 4096);
        self::$sockets[] = $this->mysock;
    }


    /**
    * Main function
     * 
    */
    FUNCTION runServer()
    {
        $sock_id = 0;
        $client_id = 0;

        while ( true )
        {
            if ( empty(self::$sockets) )
            {
                self::$sockets[$sock_id] = $this->mysock;
                $sock_id++;
            }

            $read = self::$sockets;
            $write = $except = null;

            foreach ( $read as $socket )
            {
                if ( $socket == $this->mysock )
                {
                    //Accepting new clients
                    while ( ($client = socket_accept($socket) ) )
                    {
                        foreach ( $this->clients as $key=>$clientThread )
                        {
                            echo 'Thread is closed : '.$clientThread->getIsClosed() . "\n";

                            if($clientThread->getIsClosed() == 1 || $clientThread->isTerminated() || !$clientThread->isRunning())
                            {
                                unset($this->clients[$key]);
                                $clientThread->kill();
                            }
                            else
                            {
                                $responce = $clientThread->isThreadAlive();
                                if($clientThread->getIsClosed() == 1 || !$responce || $clientThread->isTerminated())
                                {
                                    unset($this->clients[$key]);
                                    $clientThread->kill();
                                }
                                echo 'RESPONCE is: ' . $responce . "\n";
                            }
                        }
                        echo 'Count of clients arr is: '. count($this->clients) . "\n";
                        $this->clients[$client_id] = new Client($client, $sock_id, $client_id);
                        $client_id++;

                    }
                    // Start The Threads
                    foreach ( $this->clients as $key=>$clientThread )
                    {
                        if( !$clientThread->isStarted())
                        {
                            $clientThread->start();
                        }
                    }
                }
            }
        }
    }

}

我的客户类别是:

class Client extends Thread {

    public $stop = false;
    public $Timeout = 4000;  //millisecounds
    public $CurrentTime = 0;
    public $CurrentTimeout = 0;
    public $isClosed; // 0 - false; 1 - true;
    public $isWorking = 1; // 0 - false; 1 - true;
    private $SocketPort = PORT_NUMBER;
    private $SOCK_ID;
    private $CLIENT_ID;

    function setIsClosed($isClosed)
    {
        $this->isClosed = $isClosed;
    }

    function getIsClosed()
    {
        return $this->isClosed;
    }

    function isThreadAlive()
    {
        return true;
    }

    public FUNCTION __construct($socket, $sock_id, $client_id)
    {
        $this->socket = $socket;
        $this->SOCK_ID = $sock_id;
        $this->CLIENT_ID = $client_id;
        $this->isClosed = 0;

        $this->start();
    }

    protected function __distruct()
    {
        gc_collect_cycles();
    }

    FUNCTION disconnect($client)
    {
        $this->socketWriteWithChr10($client, 'Successfuly Disconnected from Server.');

        $this->isClosed = 1;
        $this->stop = true;
        socket_shutdown($client, 2);
        socket_close($client);
        $this->__distruct();
   }

    public FUNCTION run()
    {
        $client = $this->socket;
        $this->connect($client);

        while ( true )
        {
            $command = socket_read($client, 2048) or $this->stop = true;

            if ( $command === false || $command == '' )
            {
                $this->socketWriteWithChr10($client, 'Nothing to read! Successfuly Disconnected from Server.');
                $this->stop = true;
                $this->isClosed = 1;
                socket_shutdown($client, 2);
                socket_close($client);
                break;
            }

            $this->getCommand($client, $command);
            if($this->stop)
            {
                break;
            }
        }

    }


    public FUNCTION getCommand($client, $input)
    {
        switch (trim($input))
        {
            case 'FILE':
                //Filename to save
                file_put_contents('../SOCKET_FILES/' . $ID . '/' . $Dirs . $FILENAME, fileContent);break;

            default :
                $this->socketWriteWithChr10($client, 'unknown command');
                break;
        }
    }
}

当我连接 1MB 时,当我断开连接时,1MB 减少,但是当我发送文件时,我得到内存泄漏。当客户端未连接时,我可以减少内存,但如果我发送文件,内存会增长,我必须重新启动我的服务器。

客户端程序这样做:

  1. 连接
  2. 发送命令文件
  3. 发送 ID、Dirs 等参数。
  4. 服务器保存此文件并将写入的文件发送给客户端。
  5. 客户端通过disconnect命令关闭连接(服务器命中方法disconnect)。

客户端程序在 22 次迭代中一次发送 6 个文件。

在此步骤中,内存会增长,但我无法减少它。奇怪的事实是我减少了我的客户数组。 会是什么?我不擅长 linux。我只使用 htop。

我被谷歌搜索并尝试了许多示例,但问题仍然存在。 谢谢。

【问题讨论】:

    标签: php sockets memory-leaks


    【解决方案1】:

    我找到了。问题是1个客户端尝试一次发送多个文件,服务器无法及时关闭所有文件。

    【讨论】:

      猜你喜欢
      • 2015-08-26
      • 2011-07-21
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      • 2013-08-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      相关资源
      最近更新 更多