套接字服务器PHP中的内存泄漏

时间:2015-11-30 09:48:19

标签: php sockets memory-leaks

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(服务器命中方法断开连接)关闭连接。
  6. 客户端程序一次发送6个文件,同时进行22次迭代。

    在这个步骤中,内存增长,我无法减少它。奇怪的事实是我减少了我的客户端数组。 它能是什么?我对linux不好。我只使用htop。

    我用Google搜索并尝试了很多例子,但问题仍然存在。 感谢。

1 个答案:

答案 0 :(得分:0)

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