2010-10-27 10 views
1

J'écris un petit script pour voir si certains ports sur certains périphériques sont en cours d'utilisation ou sont ouverts. Mon code est:PHP Sockets, n'importe quel moyen d'accélérer cela

for($c=1;$c<=16;$c++){ 
    echo "<tr><td>Pod " . $c . "</td>"; 
    for ($d=5000;$d<=5010;$d++){ 
    $tmp=fsockopen("10.0.0." . $c,$d,$erstr, $errno, 1); 
    if($tmp){ 
     echo "<td class='o'>OPEN</td>"; 
     fclose($tmp); 
    } 
    else{ 
     echo "<td class='u'>IN USE</td>"; 
    } 
    } 
    ob_flush(); 
    flush(); 
    echo "</tr>\n"; 
} 
echo "</table>"; 

De toute évidence, il y a beaucoup de connexions, et cela prend actuellement une dizaine de secondes. Je me demandais si je pouvais faire en sorte que ce soit un peu plus rapide? Merci pour l'aide!

+0

Êtes-vous sur un environnement Linux? –

+0

Oui, je suis sur un environnement Linux. – Joseph

Répondre

2

Une façon d'accélérer considérablement est d'obtenir asynchrone. À l'heure actuelle, si l'un des hôtes est lent, il ralentira l'ensemble du pipeline parce que vous en faites un juste après l'autre. PHP n'a pas vraiment d'AIO basé sur les événements (select), ni même de threading. Il a cependant une fourchette dans un environnement Linux. L'exemple suivant n'a pas été testé, mais est une idée générale sur la façon de faire des entrées/sorties asynchrones en php:

<?php 

$childrenArr = array(); 
$childrenLeft = array(); 

for($c=1;$c<=16;$c++){ 
    for ($d=5000;$d<=5010;$d++){ 
    $pid = pcntl_fork(); 
    if ($pid == -1) { 
     die("Could not fork"); 
    } else if ($pid) { 
     $childrenArr[$pid] = array($c, $d); 
     $childrenLeft[$pid] = 1; 
    } else { 
     $tmp=fsockopen("10.0.0." . $c,$d,$erstr, $errno, 1); 
     exit(($tmp) ? 1 : 0); 
    } 
    } 
} 

$results = array(); 

while (count($childrenLeft) > 0) { 
     $oldPid = pcntl_waitpid(-1, $status, WNOHANG); 
     if (pcntl_wifexited($status)) { 
       unset($childrenLeft[$oldPid]); 
       list($c, $d) = $childrenArr[$oldPid]; 
       $results[$c . "_" . $d] = pcntl_wexitstatus($status); 
     } 
     usleep(100); 
} 

for($c=1;$c<=16;$c++){ 
    echo "<tr><td>Pod " . $c . "</td>"; 
    for ($d=5000;$d<=5010;$d++){ 
    if ($results[$c . "_" . $d]) { 
     echo "<td class='o'>OPEN</td>"; 
    } 
    else { 
     echo "<td class='u'>IN USE</td>"; 
    } 
    } 
    ob_flush(); 
    flush(); 
    echo "</tr>\n"; 
} 
echo "</table>"; 
+0

Cela fonctionne beaucoup plus vite! J'ai trouvé quelques problèmes que je vais essayer de résoudre. Premièrement, l'exécution de PHP dans le navigateur ne me donne pas les données "IN USE" ou "OPEN", mais l'exécute à partir de la CLI. En ce moment, je redirige juste la sortie vers un fichier HTML et l'exécute, pas grave. Merci pour la bonne base! – Joseph

2

Si un port donné n'écoute/n'accepte pas, vous subirez tous les délais d'attente TCP sur les réémissions de paquets SYN envoyées pendant le three-way handshake. C'est la conception du TCP - nous ne pouvons pas changer cela.

Une chose que je peux recommander est le passage de flux au socket functions et essayer sans blocage - créer vos 160 prises, les mettre à non-blocking, initier tous les connect ions, attendez sur eux dans select avec un délai d'attente décroissant, drapeau de la ceux qui reviennent lisibles. Faites cela en boucle jusqu'à ce que vous passiez, disons, une seconde entière. Maintenant, vous obtenez une liste des paires hôte/port TCP ouvertes, et une liste de vraisemblablement fermés, et vous avez passé un fixe quantité de temps.

Clause de non-responsabilité: Je ne fais jamais de mise en réseau en PHP, donc cela peut être totalement inutile.

+0

Cela ressemble à un moyen supplémentaire de gagner du temps, donc je vais essayer de mettre en œuvre ces idées avec le code Mike posté ci-dessus. Merci à vous deux! – Joseph