Mettre en attente l'écoute d'une socket

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Mettre en attente l'écoute d'une socket

Re: Mettre en attente l'écoute d'une socket

par stopher » 18 juin 2010, 14:30

Tu peux toujours jouer avec les signaux :

http://us.php.net/manual/fr/function.pcntl-signal.php

Re: Mettre en attente l'écoute d'une socket

par JBzh » 18 juin 2010, 14:25

Effectivement c'est au multithreading que je pensais, sans trouver de possibilité de le faire. Un coup d'oeil du coté de stream_select() m'avait pourtant donné un espoir.

Si je fork, il n'y a plus aucune interopérabilité entre le code du processus fil et celui du parent ? Il reste possible de lui envoyer des signaux via
posix_kill($pid, SIGKILL);
par exemple. Mais si j'ai bien compris les deux processus ne peuvent pas communiquer directement (hormis par une socket raw par exemple mais nous en reviendrions au premier problème).

EDIT: errata, avec la gestion de la mémoire partagée ça me convient. J'aurais plusieurs process, tant pis, mais la communication est possible. Cf. http://www.noisette.ch/wiki/index.php/PHP/Multithread

Re: Mettre en attente l'écoute d'une socket

par stopher » 18 juin 2010, 13:49

Si tu ne veux pas forker , alors il me semble bien que c'est impossible ...

PHP est procédural , il ne gère malheureusement pas de thread qui aurait été une solution ici ..
Pour moi , tu n'as pas le choix ... tu dois forker

Ch.

Mettre en attente l'écoute d'une socket

par JBzh » 18 juin 2010, 11:06

Bonjour,


Je souhaite mettre en écoute une socket sans pour autant bloquer l'exécution du code. Il semble que la fonction socket_set_nonblock() soit une solution.
Néanmoins, c'est la fonction complète comportant une boucle infinie que je souhaite mettre de coté tant que le serveur ne reçoit pas de message dans sa socket.

J'ai une fonction StartSocketServ() dans laquelle j'ai une boucle avec un $NewSockClient['SockHd'] = socket_accept($this->SockServHd); et je voudrais que cette fonction soit lancée, et que le code continue à s'exécuter. Sans pour autant forker, je voudrais garder un seul processus.

Si je ne veux pas créer un autre processus c'est justement parce que je veux me servir des sockets notamment pour arrêter le processus en cours. J'utilise la classe System_Daemon du projet Pear.

Le code est le suivant, écoute simple sur une socket, et arrêt de l'écoute lorsque l'on reçoit "DIE" :
    /**
     * Socket server
     **/
    protected function StartSocketServ($address,$port) {
        try {
            System_Daemon::log(System_Daemon::LOG_NOTICE, 'Creating Socket to wait for clients');
            $this->SockServHd = socket_create(AF_INET, SOCK_STREAM, 0);
            if (!@socket_bind($this->SockServHd, $address, $port))
            {
                throw new LogicException('Could not bind socket on address ' . $address . ' and port ' . $port.'.');
            }
            else 
            {
                if (!@socket_listen($this->SockServHd)) 
                {
                    throw new LogicException('Could not listen.');
                }
                else
                {
                    $NewSockClient = Array('SockHd'   => null,
                                           'ip'       => null,
                                           'port'     => null);
                    $SockServerIsAlive = true;
                    while ($SockServerIsAlive)
                    {
                        $NewSockClient['SockHd'] = socket_accept($this->SockServHd);
                        @socket_getpeername($NewSockClient['SockHd'], $NewSockClient['ip'], $NewSockClient['port']);
                        System_Daemon::log(System_Daemon::LOG_NOTICE, 'Socket server - New client connected from '.$NewSockClient['ip'].' port '.$NewSockClient['port']);
                        $sock_read = socket_read($NewSockClient['SockHd'], 1024);
                        System_Daemon::log(System_Daemon::LOG_NOTICE, 'Socket server - Received message: '.$sock_read);
                        if ($sock_read == "DIE")
                        {
                            $msg = "BYE";
                            if (!@socket_write($NewSockClient['SockHd'], $msg, strlen($msg))) System_Daemon::log(System_Daemon::LOG_WARNING, 'Socket server - Could not send bye in response to a DIE command');
                            else System_Daemon::log(System_Daemon::LOG_DEBUG, 'Sent BYE in response to DIE command');
                            if (!@$this->SockClose($NewSockClient['SockHd'])) System_Daemon::log(System_Daemon::LOG_WARNING, 'Socket server - Could not close client socket. Errorno: '.socket_last_error().' Error: '. socket_strerror(socket_last_error()) );
                            if (!@$this->SockClose($this->SockServHd)) System_Daemon::log(System_Daemon::LOG_ERR, 'Socket server - Could not close SERVER socket. Errorno: '.socket_last_error().' Error: '.socket_strerror(socket_last_error()));
                            else System_Daemon::log(System_Daemon::LOG_NOTICE, 'Server socket closed successfully');
                            unset($this->SockServHd);
                            $SockServerIsAlive = false;
                        }
                        else
                        {
                            $msg = "ERROR - Unknown command";
                            if (!@socket_write($NewSockClient['SockHd'], $msg, strlen($msg))) System_Daemon::log(System_Daemon::LOG_WARNING, 'Socket server - Could not send error message in response to an unknown command');
                            if (!@$this->SockClose($NewSockClient['SockHd'])) System_Daemon::log(System_Daemon::LOG_WARNING, 'Socket server - Could not close client socket. Errorno: '.socket_last_error().' Error: '.socket_strerror(socket_last_error()));
                        }
                    }
                    System_Daemon::stop();
                }
            }
        }
        catch (Exception $e) 
        {
            $lasterrno = socket_last_error();
            System_Daemon::log(System_Daemon::LOG_EMERG, 'Socket error: ' . $e->getMessage().' Errno: '.$lasterrno.' ( '.socket_strerror($lasterrno).' )');
            System_Daemon::log(System_Daemon::LOG_EMERG, 'Stopping daemon');
            $this->stop();
            exit(1);
        }    
    }
    
    function SockClose($Sock) {
        if (!@socket_shutdown($Sock, 2)) System_Daemon::log(System_Daemon::LOG_WARNING, 'Socket server - socket_shutdown error. Errorno: '.socket_last_error().' Error: '.socket_strerror(socket_last_error()));
        return socket_close($Sock);
    }
Cette fonction est appelée ici :
    public function start() {
        System_Daemon::start();
        $this->StartSocketServ(0.0.0.0,15100);
        try {
            while (!System_Daemon::isDying()) {
                System_Daemon::log(System_Daemon::LOG_DEBUG, 'I am alive');
                System_Daemon::iterate(2);
            }
        } 
        catch (Exception $e) 
        {
            System_Daemon::log(System_Daemon::LOG_EMERG, 'Unhandled Exception: ' . $e->getMessage());
            System_Daemon::log(System_Daemon::LOG_EMERG, 'stopping daemon');
            System_Daemon::stop();
            throw $e;
        }    
    }
Bien évidemment tel que c'est codé ici le code après $this->StartSocketServ(0.0.0.0,15100); n'est jamais exécuté.
Je voudrais donc le modifier, pour que La fonction StartSocketServ() n'empêche pas le code de s'exécuter ensuite.