• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

PHP Sockets - Przechowywanie w sesji (Symfony, Ratchet)

Object Storage Arubacloud
0 głosów
200 wizyt
pytanie zadane 7 lipca 2017 w PHP przez elaen Gaduła (4,760 p.)

Tworze sobie serwer na socketach do pewnej gry, i mam problem z przechowywaniem informacji o klientach...
Napisałem sobie Event listener który odpala event w zależności od 1 pakietu w przychodzącej wiadomości. Wszystko odpala się OK i działa w porządku, jednak nie mam możliwości z gromadzeniem informacji o klientach połączonych do serwera. Próbuje użyć sesji, ale w każdym następnym kliencie się czyści lub się po prostu nie utworzyła. Próbowałem użyć Memcache i PDOSessionStorage.

Komenda która odpala serwer:

<?php
/**
 * {@inheritdoc}
 */
protected function execute(InputInterface $input, OutputInterface $output)
{
    $output->writeln('Server starting');
    $communication = $this->getContainer()->get('uo_server.server_communication');

    $pdo = new \PDO('mysql:host=127.0.01;dbname=uo-session', 'root', null);
    $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    $dbOptions = array(
        'db_table'        => 'sessions',
        'db_id_col'       => 'sess_id',
        'db_data_col'     => 'sess_data',
        'db_time_col'     => 'sess_time',
        'db_lifetime_col' => 'sess_lifetime',
        'lock_mode'       => 0
    );

    $sessionProvider = new PdoSessionHandler($pdo, $dbOptions);

    $server = IoServer::factory(
        new SessionProvider($communication, $sessionProvider),
            2593,
            '127.0.0.1');

    $server->run();
}

 

Fragment Message component:

 

<?php

    function __construct(ContainerInterface $container)
{
    $this->container = $container;
    $this->packetDispatcher = $container->get('uo_server.packets_event_dispatcher');
    $this->connections = new ArrayCollection();
}

/**
 * When a new connection is opened it will be passed to this method
 * @param  ConnectionInterface $conn The socket/connection that just connected to your application
 * @throws \Exception
 */
function onOpen(ConnectionInterface $conn)
{
    $this->connections->add($conn);
    /**
     * @var Session $session
     */
    $session = $conn->Session;
    $session->setId('session_'.$conn->resourceId);
    $session->start();
}

/**
 * This is called before or after a socket is closed (depends on how it's closed).  SendMessage to $conn will not result in an error if it has already been closed.
 * @param  ConnectionInterface $conn The socket/connection that is closing/closed
 * @throws \Exception
 */
function onClose(ConnectionInterface $conn)
{
    $conn->Session->save();

    if($this->connections->contains($conn)) {
        $this->connections->removeElement($conn);
    }
}

/**
 * If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown,
 * the Exception is sent back down the stack, handled by the Server and bubbled back up the application through this method
 * @param  ConnectionInterface $conn
 * @param  \Exception $e
 * @throws \Exception
 */
function onError(ConnectionInterface $conn, \Exception $e)
{
    $conn->Session->save();

    // TODO: Implement onError() method.
}

/**
 * Triggered when a client sends data through the socket
 * @param  \Ratchet\ConnectionInterface $from The socket/connection that sent the message to your application
 * @param  string $msg The message received
 * @throws \Exception
 */
function onMessage(ConnectionInterface $conn, $msg)
{
    $this->packetDispatcher->dispatchEvent($conn, $msg);
    $conn->Session->save();
}

Funkcja dispatch-ująca event-y:

<?php

public function dispatchEvent(ConnectionInterface $sender, $msg)
{

    $data = unpack('C*',$msg);
    $eventPacket = "0x".DataConverter::convertDecimalToHex($data[1]);
    $event = isset($this->packetsEvents[$eventPacket]) ? $this->packetsEvents[$eventPacket] : null;

    if ($event !== null) {
        $incomingEvent = new MainEvent($sender, $msg);
        if ($this->dispatcher->hasListeners($event)) {
            $this->dispatcher->dispatch($event, $incomingEvent);
        } else {
            Logger::Log('Event :'.$event.' is not implement yet!');
        }

    }
}

 

No i przykładowy event logowania:

 

<?php

    public function onLogin(MainEvent $event)
{
    $this->event = $event;
    $packetReader = new PacketReader($this->event->getMessage());
    $login = $packetReader->getByteFrom(2, 30);
    $password = $packetReader->getByteFrom(32, 30); //todo some byte on the end?

    if($this->accountFinder->checkAccountAccess($login, $password)) {
        Logger::Log('try to log:'.$login . '/' . $password.';');
        $account = $this->accountFinder->getAccount($login, $password);
        return $this->loginSuccess($account);
    }

    if($this->serverInfo['auto_account'] && $this->accountFinder->checkAccountExist($login) === false) {
            Logger::Log('account not found, but autoaccounting is on. Account created;');
            $account = $this->accountFinder->createUser($login, $password);
            return $this->loginSuccess($account);
    }

    Logger::Log('login for credientals: '.$login.'/'.$password.' failure;');
    $this->loginFailure($login);
}

private function loginSuccess(Account $account)
{
    $ip = explode(".", $this->serverInfo['host']);
    $packet = new Packet;
    $packet
        ->prependPacket("A8")
        ->appendPacket("FF")
        ->appendPacket(DataConverter::convertDecimalToHex(1), 4)
        ->appendPacket(DataConverter::convertDecimalToHex(1), 4)
        ->appendPacket(DataConverter::convertStringToHex($this->serverInfo['name']), 64, Packet::PAD_FROM_RIGHT)
        ->appendPacket(DataConverter::convertDecimalToHex($this->serverInfo['full']), 2) //todo full is not from PARAM!!!
        ->appendPacket(DataConverter::convertDecimalToHex($this->serverInfo['timezone']), 2);
    for ($i=3; $i>=0; $i--) {
        $packet->appendPacket(DataConverter::convertDecimalToHex($ip[$i]), 2);
    }

    $currentLenght = $packet->getPacketSize();
    $packet->injectPacket(DataConverter::convertDecimalToHex($currentLenght + 2), 4, 2);
    $this->event->setToSession('accountId', $account->getId());
    $this->event->getClientSession()->save();
    $this->event->getClient()->send($packet->getPacket());
    return true;
}

/**
 * TODO FAILURE FROM BANS ETC.
 * @return bool
 */
private function loginFailure($login)
{
    $reason = 0;

    if ($this->accountFinder->checkAccountExist($login)) {
        $reason = 3;
    }

    $packet = new Packet;
    $packet
        ->prependPacket("82")
        ->appendPacket(DataConverter::convertDecimalToHex($reason), 2);
    $this->event->getClient()->send($packet->getPacket());
    return true;
}

 

Kiedy próbuje zaczytać w następnym event-cie coś z  sesji no to zwraca mi niestety NULL-a. Dumpując sobie sesje ewidentnie widać że ona nie istnieje. Tak samo w przypadku PDOSession nie dodaje się wpis do DB, także definitywnie coś tu nie działa. Czy ktoś może miał podobny problem i udało mu się go rozwiązać ? Chyba że istnieje jakiś inny sposób na przechowywanie danych o klientach?

 

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
1 odpowiedź 865 wizyt
pytanie zadane 28 września 2018 w PHP przez tomek923 Początkujący (480 p.)
0 głosów
0 odpowiedzi 703 wizyt
pytanie zadane 1 marca 2019 w JavaScript przez maciekk34 Nowicjusz (180 p.)
0 głosów
1 odpowiedź 184 wizyt
pytanie zadane 8 listopada 2019 w PHP przez michal_php Stary wyjadacz (13,700 p.)

92,538 zapytań

141,377 odpowiedzi

319,456 komentarzy

61,923 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...