gestion des sockets coté serveur en php

Petit nouveau ! | 1 Messages

05 sept. 2013, 11:22

Bonjour,

J'ai réalisé un Web Service en php qui se met en écoute sur un port (90092) et qui reçoit des requêtes en mode POST.
Je n'ai aucun souci SAUF (il faut bien qu'il y ait un "sauf") avec un client développé en java et qui utilise la clase apache.commons.hhtpclient d'Apache (donc impossible de savoir comment ça fonctionne à l'intérieur, le code source du client se contente d'indisuer l'URL, le coprs de la requête et effectue un POST, tout le reste est géré en interne).

Mon souci se situe après le socket_accept() : Le client ne m'envoie rien du tout.

Si je remplace mon serveur par une autre application serveur (développée en DELPHI) sur le même port même serveur (donc réellement à la place de mon serveur) , l'application serveur Delphi reçoit bien la requête en POST => J'en déduis que le soucis provient bien de mon code en php....
L'un d'entre vous aurait-il une idée ???

Voici mon code j'ai essayer d'épurer le plus possible des traitements ne concernant pas les sockets....

Dans mes traces je vois bien la connexion du client, puis..... aucune trace de tyep "read du socket..." et le client reste bloqué (normal car je ne lui réponds pas) avec de partir en timeout...

Merci, car là je bloque totalement, pour moi après avoir ouvert le socket (socket_accept()) la connexion est ouverte et le client doit m'envoyer la requête.... il le fait bien avec d'autres serveurs, pas avec le mien...
<?php
	require_once ("class/Klogger.php");
	require_once ("class/AccesTable.php");	


	/* Déclaration des variables */
	$Debug = false; 		// En mode debug, de nombreuses traces sont générées
	$log = null;			// objet de Klogger, pour la génération des traces
	$MaxSessions = 5;		// Nombre paximum de connexions simultanées sur le socket 
	$clients = array();		//Liste des clients (sessions ) ayant ouvert un socket de communication
	$boucle = true;			// boucle infinie sur la lecture des sockets 
	$ret = null;			// Variable pour tester les retours de procedures
	$Buffer = array();		// Tableau de strings permttant la bufferisation des paquets reçus pour cahque client jusqu'à lecture du 0xff (fin de requete selon KAPI2)
	$Priority = 5;

	// Mise en attente sur le port TCP
	$address = '127.0.0.1';
	$Port=90092;
	if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
		$log->LogFatal ("socket_create() Erreur: " . socket_strerror(socket_last_error()));
		exit (1);
	}
	socket_setopt($sock, SOL_SOCKET, SO_REUSEADDR, 1 );
	
	$log->LogDebug ("socket créé");

	if (socket_bind($sock, $address, $Port) === false) {
		$log->LogFatal ("socket_bind() Erreur : " . socket_strerror(socket_last_error($sock)));
		exit (1);
	}
	$log->LogDebug ("bind effectué ");
	if (socket_listen($sock, $MaxSessions) === false) {
		$log->LogFatal ("socket_listen() Erreur : " . socket_strerror(socket_last_error($sock)));
		exit (1);
	}
	$log->LogInfo ("Initialisation du module terminee. En attente de requetes de CLEVA");
	$clients = array($sock);
  
	$null = NULL;
    while ($boucle) {
        // Copie de la liste des clients
        $read = $clients;
		$write = $clients;
		$except = $clients;
		$utime = 1000;
		$Null = NULL;

        // Y a-t-il des chose à faire pour certains clients ?
  
		if (socket_select($read, $Null, $Null ,$null) < 1) {
			continue;
		} 
	 
        // Teste si un nouveau client tente de se connecter
        if (in_array($sock, $read)) {
            // Ajout du nouveau client

			$clients[] = $newsock = socket_accept($sock);
         
			// socket_getpeername($newsock, $ip); // Juste pour tracer...
            
            $log->LogDebug("Nouvelle connexion sur le socket $newsock, il y a actuellement ".(count($clients) - 1)." connexions actives Microtime :".microdatetime() );
            $Buffer[$newsock] = "";                

        }
        
        // boucle sur tous les clients pour lesquels des données ont été reçues
        foreach ($read as $read_sock) {
            // on lit au maximum 4KB à chaque passage

            $data = @socket_read($read_sock, 4096, PHP_NORMAL_READ);
          
            // Teste si le client s'est déconnecté
            if ($data === false) {
                // Suppression du client de la liste
                $key = array_search($read_sock, $clients);
				// Fermeture du socket
				socket_close($read_sock);
                unset($clients[$key]);
				$Buffer[$read_sock] = "";
                $log->LogDebug("Socket ferme : $read_sock");
                // on continue...
                continue;
            }
			$log->LogDebug("read du socket ".$read_sock." avec data=->$data<-" );		
			/* Traitement de la requête reçue avec mise en Buffer jusqu'à fin de récéeption des paquets
			{
			.....
			}
			*/
			
		}
	} // Fin du while inifini

    // Fermeture du socket principal
    socket_close($sock);
?>

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

05 sept. 2013, 13:13

salut,

va falloir sniffer les traces réseaux pour voir exactement ce qui se passe entre les deux.

si ton code php fonctionne avec différents clients, perso je m'orienterais vers un pb coté client.

est tu certain que le client java soit bien configuré ?
est ce qu'il y a un log quelconque du code java ?

cette ligne "$log->LogDebug("read du socket ".$read_sock." avec data=->$data<-" ); " n'est pas exécutée ?

les traces jusqu'au while sont bien présente ?

je vois
<?php
if (socket_select($read, $Null, $Null, $null) < 1) {
        continue;
    }
pourquoi créer $null et $Null ? et pourquoi ne pas simplement utiliser null ? (ok a cause de socket_select qui passe les infos par référence donc variables obligatoire).

est ce que tu vois une de nouvelle connexion ?
si tu vire l'arobase de @socket_read($read_sock, 4096, PHP_NORMAL_READ); est ce que tu as un message d'erreur ?

le socket_close() en dernière ligne du script ne sert à rien vu qu'elle ne sera jamais exécutée (le seul moyen d’arrêter le script c'est un kill. La ligne ne sera donc pas executée et je ne suis pas certain que le garbage collector ferme la socket dans ce cas, je ne suis même pas certain qu'il fasse sont taff dans ce cas ;) ).


tu as un $log = null qui fait que par la suite tu ne peux utiliser le logger => tu devrais avoir une erreur si ce n'est pas le cas error_reporting = E_ALL c'est obligatoire en dev ;)

en dehors de ça le code semble bon.

si je trouve un peu de temps j’essaierais un client java la dessus (je te promet rien).

@+
Il en faut peu pour être heureux ......