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.