簡體   English   中英

套接字服務器PHP中的內存泄漏

[英]Memory leaks in socket server PHP

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. 發送參數,例如ID,Dirs等。
  3. 服務器保存該文件,並向客戶端發送該文件。
  4. 客戶端通過命令斷開連接(服務器命中方法斷開連接)關閉連接。

客戶端程序一次發送6個文件,同時進行22次迭代。

在這一步中,內存增加了,我無法減少它。 奇怪的事實是我減少了我的客戶人數。 會是什么 我對linux不好。 我只使用htop。

我被谷歌搜索並嘗試了很多例子,但是問題仍然存在。 謝謝。

我找到了。 問題是1個客戶端嘗試一次發送多個文件,而服務器無法及時關閉所有文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM