Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/237.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Rachet聊天应用程序-应用程序运行一段时间后,建立连接后立即关闭_Php_Laravel 4_Ratchet - Fatal编程技术网

Php Rachet聊天应用程序-应用程序运行一段时间后,建立连接后立即关闭

Php Rachet聊天应用程序-应用程序运行一段时间后,建立连接后立即关闭,php,laravel-4,ratchet,Php,Laravel 4,Ratchet,我们正在使用Laravel4和Ratchet来创建一个聊天应用程序。一切正常运行约14-20小时。一段时间后,聊天应用程序停止运行。建立从客户端到服务器的连接,但之后服务器立即关闭连接 我们的日志文件中没有报告任何错误,而且我们无法在开发环境中复制该问题的事实也没有帮助 在服务器上重新启动聊天应用程序可将问题修复14-20小时 管理器配置: [program:chat] command = bash -c "ulimit -n 10000 && /usr/bin/

我们正在使用Laravel4和Ratchet来创建一个聊天应用程序。一切正常运行约14-20小时。一段时间后,聊天应用程序停止运行。建立从客户端到服务器的连接,但之后服务器立即关闭连接

我们的日志文件中没有报告任何错误,而且我们无法在开发环境中复制该问题的事实也没有帮助

在服务器上重新启动聊天应用程序可将问题修复14-20小时

管理器配置:

[program:chat]
command         = bash -c "ulimit -n 10000 && /usr/bin/php /var/www/artisan setup:chat --env=staging"
process_name    = chat
numprocs        = 1
autostart       = true
autorestart     = true
user            = root
stdout_logfile      = /var/www/app/storage/logs/chat_info.log
stdout_logfile_maxbytes = 1MB
stderr_logfile      = /var/www/app/storage/logs/chat_error.log
stderr_logfile_maxbytes = 1MB
SetupChatCommand.php(Laravel设置聊天命令):


您确定进程本身在停止工作后不再运行了吗?我不是问你是否确定它不工作,更重要的是它在运行
$ps aux | grep artisan
时没有显示。我们遇到了类似的问题,但在我们的案例中,只是在大约相同的时间段后,与数据库的连接被删除。(过程本身仍在正常运行)没关系,我误解了你的部分问题。。我仍然怀疑可能是数据库连接被断开,但我认为如果发生这种情况,会在
app/storage/logs/laravel.log
中报告某些情况。您好@watcher,我可以确认聊天应用停止工作后进程仍在运行。当我“ps aux|grep php”时,我得到了两次聊天过程:“bash-c ulimit-n 10000&&/usr/bin/php/var/www/artisan-setup:chat--env=staging”和“/usr/bin/php/var/www/artisan-setup:chat--env=staging”。第一个是用于监视第二个进程的主管进程。@watcher你们是如何修复数据库连接被删除的,你们知道是什么原因导致的吗?我很乐意探索这个场景,看看应用程序是否仍然停止工作。我们不使用supervisor,但我们的“supervisor”每12小时重新启动一次流程:)。没有混乱,没有大惊小怪,但对你来说,这可能不是一个解决办法。
<?php

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

use Application\Chat\Server;

class SetupChatCommand extends Command {

    /**
     * The console command name.
     *
     * @var string
     */

    protected $name = 'setup:chat';

    /**
     * The console command description.
     *
     * @var string
     */

    protected $description = 'Setup the chat server';

    /**
     * Create a new command instance.
     *
     * @return void
     */

    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */

    public function fire()
    {
        $server = new Server();
        $server->run();
    }

}
<?php namespace Application\Chat;

use React\EventLoop\Factory;
use React\Socket\Server as Reactor;
use Ratchet\Server\IoServer;
use Ratchet\Server\FlashPolicy;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;

class Server {

    const CHAT_PORT = 7778;
    const FLASH_PORT = 843;

    public function __construct()
    {
        $this->_setup();
    }

    private function _setup()
    {
        $loop = Factory::create();

        $web_socket = new Reactor($loop);
        $web_socket->listen(self::CHAT_PORT, '0.0.0.0');

        $this->_server = new IoServer(
            new HttpServer(
                new WsServer(
                    new Service()
                )
            )
          , $web_socket
          , $loop
        );

        $flash_policy = new FlashPolicy();
        $flash_policy->addAllowedAccess('*', self::CHAT_PORT);

        $flash_socket = new Reactor($loop);
        $flash_socket->listen(self::FLASH_PORT, '0.0.0.0');

        $flash_server = new IoServer($flash_policy, $flash_socket);
    }

    public function run()
    {
        $this->_server->run();
    }

}
<?php namespace Application\Chat;

use SplObjectStorage;

use Ratchet\ConnectionInterface;
use Ratchet\MessageComponentInterface;

class Service implements MessageComponentInterface {

    public function __construct()
    {
        $this->_setupClients();
    }

    /**
     * Clients
     */

    private $_clients = null;

    private function _setupClients()
    {
        $this->_clients = new SplObjectStorage();
    }

    public function getClientByConnection($connection)
    {
        foreach ($this->_clients as $client)
        {
            if($client->getConnection() === $connection)
            {
                return $client;
            }
        }

        return null;
    }

    public function getClientsByRoom($room)
    {
        $clients = array();

        foreach ($this->_clients as $client)
        {
            if($client->getRoom()->id === $room->id)
            {
                array_push($clients, $client);
            }
        }

        return $clients;
    }

    /**
     * Input
     */

    private function _handleInput($client, $input)
    {
        if(empty($input) || empty($input['type']) || empty($input['content'])) return;

        switch ($input['type'])
        {
            case 'session.set':
                $this->_handleInputSetSession($client, $input['content']);
                break;

            case 'room.set':
                $this->_handleInputSetRoom($client, $input['content']);
                break;

            case 'message':
                $this->_handleInputMessage($client, $input['content']);
                break;
        }
    }

    private function _handleInputSetSession($client, $input)
    {
        $client->setSession($input);
    }

    private function _handleInputSetRoom($client, $input)
    {
        $client->setRoom($input);
    }

    private function _handleInputMessage($client, $input)
    {
        $message = $client->message($input);

        if($client->hasRoom() && $message)
        {
            $clients = $this->getClientsByRoom($client->getRoom());

            foreach ($clients as $other)
            {
                if($other !== $client)
                {
                    $other->getConnection()->send(json_encode(array(
                        'type'    => 'message.get'
                      , 'content' => $message->toArray()
                    )));
                }
            }
        }
    }

    /**
     * Callbacks
     */

    public function onOpen(ConnectionInterface $connection)
    {
        $client = new Client($connection);
        $this->_clients->attach($client);
    }

    public function onMessage(ConnectionInterface $connection, $input)
    {
        $client = $this->getClientByConnection($connection);
        $input    = json_decode($input, true);

        $this->_handleInput($client, $input);
    }

    public function onClose(ConnectionInterface $connection)
    {
        $client = $this->getClientByConnection($connection);

        if($client)
        {
            $this->_clients->detach($client);
        }
    }

    public function onError(ConnectionInterface $connection, \Exception $e)
    {
        $client = $this->getClientByConnection($connection);

        if($client)
        {
            $client->getConnection()->close();
        }
    }

}
<?php namespace Application\Chat;

use App;
use Config;

use Application\Models\ChatRoom;
use Application\Models\ChatRoomUser;
use Application\Models\ChatRoomMessage;
use Application\Models\File;

class Client {

    /**
     * Constructor & Destructor
     */

    public function __construct($connection = null)
    {
        if($connection)
        {
            $this->setConnection($connection);
        }
    }

    public function __destruct()
    {
        if($this->hasRoom())
        {
            $this->takenUserOfflineForRoomId($this->getRoom()->id);
        }
    }

    /**
     * Connection
     */

    protected $_connection = null;

    public function getConnection()
    {
        return $this->_connection;
    }

    public function setConnection($connection)
    {
        $this->_connection = $connection;
    }

    /**
     * Session
     */

    public function setSession($input)
    {
        Config::set('session.driver', 'database');

        $session_id = $input; 

        $session = App::make('session');
        $session->setDefaultDriver(Config::get('session.driver'));

        $session->driver()->setId($session_id);
        $session->driver()->start();

        $cartalyst_session = $session->driver()->get(
            Config::get('cartalyst/sentry::cookie.key')
        );

        if(!empty($cartalyst_session))
        {
            $this->setUserId($cartalyst_session[0]);
        }
        else
        {
            throw new \Exception('User not recognized.');
        }
    }

    /**
     * User id
     */

    private $_user_id = null;

    private function setUserId($id)
    {
        $this->_user_id = $id;
    }

    public function getUserId()
    {
        return $this->_user_id;
    }

    /**
     * Room
     */

    private $_room = null;

    public function getRoom()
    {
        return $this->_room;
    }

    public function setRoom($input)
    {
        if(empty($input) || empty($input['id']))
        {
            throw new \Exception('Invalid chat room.');
        }

        $this->_room = ChatRoom::find($input['id']);

        $this->takeUserOnlineForRoomId($this->getRoom()->id);
    }

    public function hasRoom()
    {
        if($this->_room)
        {
            return true;
        }

        return false;
    }

    /**
     * User room status
     */

    public function takeUserOnlineForRoomId($room_id)
    {
        $chat_room_user = ChatRoomUser::where('chat_room_id', '=', $room_id)
                                      ->where('user_id', '=', $this->getUserId())
                                      ->first();

        if($chat_room_user)
        {
            $chat_room_user->status = ChatRoomUser::STATUS_ONLINE;
            $chat_room_user->save();
        }
    }

    public function takenUserOfflineForRoomId($room_id)
    {
        $chat_room_user = ChatRoomUser::where('chat_room_id', '=', $room_id)
                                      ->where('user_id', '=', $this->getUserId())
                                      ->first();

        if($chat_room_user)
        {
            $chat_room_user->status = ChatRoomUser::STATUS_OFFLINE;
            $chat_room_user->save();
        }
    }

    /**
     * Message
     */

    public function message($input)
    {
        $message = new ChatRoomMessage();
        $message->user_id = $this->getUserId();
        $message->status  = ChatRoomMessage::STATUS_NEW;
        $message->content = $input['content'];

        $chat_room = $this->getRoom();
        $chat_room->messages()->save($message);

        $this->_attachInputFile($input, $message);

        $message->load('user', 'user.profile', 'user.profile.picture');

        return $message;
    }

    private function _attachInputFile($input, $message)
    {
        if(empty($input['file']) || empty($input['file']['id'])) return;

        $file = File::where('user_id', '=', $this->getUserId())
                    ->where('id', '=', $input['file']['id'])
                    ->first();

        if(!$file) return;

        $message->file()->save($file);
        $message->load('file');
    }

}