2010-10-22 9 views
6

Ho testato l'ascolto di socket PHP e ho riscontrato il problema sopra menzionato. Il mio listener di test funziona altrimenti bene, ma se un client si disconnette senza dire al server, lo script va in loop infinito fino a quando un nuovo client non si connette. Il problema sembra essere sulla linea $ready = socket_select($read, $write = NULL, $except = NULL, $tv_sec = NULL); dal momento che dovrebbe fermarsi per attendere le connessioni qui, ma invece salta l'attesa e scorre lungo il loop.Come rilevare la disconnessione del client sul listener di socket PHP?

Qualsiasi suggerimento sarebbe apprezzato.

Codice:

#!/usr/bin/php -q 
<?php 

$debug = true; 
function e($str) { 
    global $debug; 
    if($debug) { echo($str . "\n"); } 
} 

e("Starting..."); 
error_reporting(1); 
ini_set('display_errors', '1'); 

e("Creating master socket..."); 
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
$max_clients = 10; 

e("Setting socket options..."); 
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1); 
e("Binding socket..."); 
socket_bind($socket, "192.168.1.38", 20000); 
e("Listening..."); 
socket_listen($socket, $max_clients); 

$clients = array('0' => array('socket' => $socket)); 

while(TRUE) { 
    e("Beginning of WHILE"); 
    $read[0] = $socket; 

    for($i=1; $i<count($clients)+1; ++$i) { 
     if($clients[$i] != NULL) { 
      $read[$i+1] = $clients[$i]['socket']; 
     } 
    } 

    e("Selecting socket..."); 
    $ready = socket_select($read, $write = NULL, $except = NULL, $tv_sec = NULL); 
    e("socket_select returned " . $ready); 
    e("If..."); 
    var_dump($socket); 
    var_dump($read); 
    if(in_array($socket, $read)) { 
     e("If OK"); 
     for($i=1; $i < $max_clients+1; ++$i) { 
      if(!isset($clients[$i])) { 
       e("Accepting connection..."); 
       $clients[$i]['socket'] = socket_accept($socket); 

       socket_getpeername($clients[$i]['socket'],$ip); 
       e("Peer: " . $ip); 
       $clients[$i]['ipaddr'] = $ip; 

       socket_write($clients[$i]['socket'], 'Welcome to my Custom Socket Server'."\r\n"); 
       socket_write($clients[$i]['socket'], 'There are '.(count($clients) - 1).' client(s) connected to this server.'."\r\n"); 

       echo 'New client connected: ' . $clients[$i]['ipaddr'] .' '; 
       break; 
      } elseif($i == $max_clients - 1) { 
       echo 'Too many Clients connected!'."\r\n"; 
      } 

      if(--$ready <= 0) { 
       continue; 
      } 
     } 
    } 

    e("For..."); 
    for($i=1; $i<$max_clients+1; ++$i) { 
     e("In..."); 
     if(in_array($clients[$i]['socket'], $read)) { 
      e("Reading data..."); 
      $data = @socket_read($clients[$i]['socket'], 1024, PHP_NORMAL_READ); 

      if($data === FALSE) { 
       unset($clients[$i]); 
       echo 'Client disconnected!',"\r\n"; 
       continue; 
      } 

      $data = trim($data); 

      if(!empty($data)) { 
       if($data == 'exit') { 
        socket_write($clients[$i]['socket'], 'Thanks for trying my Custom Socket Server, goodbye.'."\n"); 
        echo 'Client ',$i,' is exiting.',"\n"; 
        socket_close($clients[$i]['socket']); 
        unset($clients[$i]); 
        continue; 
       } 

       for($j=1; $j<$max_clients+1; ++$j) { 
        if(isset($clients[$j]['socket'])) { 
         if(($clients[$j]['socket'] != $clients[$i]['socket']) && ($clients[$j]['socket'] != $socket)) { 
          echo($clients[$i]['ipaddr'] . ' is sending a message!'."\r\n"); 
          socket_write($clients[$j]['socket'], '[' . $clients[$i]['ipaddr'] . '] says: ' . $data . "\r\n"); 
         } 
        } 
       } 
       break; 
      } 
     } 
    } 
    if($loops == 0) { 
     $firstloop = time(); 
     $loops++; 
    } else { 
     $loops++; 
     if((time() - $firstloop) >= 5 && $loops > 25) { 
      /*for($j=1; $j<$max_clients+1; ++$j) { 
       if(isset($clients[$j]['socket'])) { 
        if($clients[$j]['socket'] != $socket) { 
         echo('Server is looping, sending keepalive...'."\r\n"); 
         if(!socket_write($clients[$j]['socket'], '-KEEPALIVE-' . "\r\n")) { 
          echo 'Client ',$j,' not found, killing...',"\n"; 
          socket_close($clients[$j]['socket']); 
          unset($clients[$j]); 
          die("debug"); 
         } 
        } 
       } 
      }*/ 
      die("Looping started.\n"); 
     } 
    } 
} 
?> 
+0

pensare a una migliore progettazione codice – Svisstack

+0

@Svisstack Di solito io non prestare molta attenzione al codice di prova, dal momento che farò una riscrittura completa strutturato se inizio un ulteriore sviluppo. – onik

+0

Per favore ho lo stesso problema, come hai potuto risolverlo? Hai fatto se ($ data === FALSE), il mio problema è che il client sia disconnesso (quando disconnetto internet) ma non ho alcuna chatnged_sockets? :( –

risposta

5

Trovato il problema, mi mancava un socket_close() dal blocco "Client disconnesso". Quindi il blocco corretta è:

if($data === FALSE) { 
    socket_close($clients[$i]['socket']); 
    unset($clients[$i]); 
    echo 'Client disconnected!',"\r\n"; 
    continue; 
} 
2

Usa get_last_error() di controllare questo.

+0

104: connessione ripristinata dal peer, ma come faccio a chiudere il socket giusto correttamente – onik

+0

questo non è un codice operativo per esso Connessione chiusa Prova simulare questo e verificare ciò che codice operativo è stato restituito da questa funzione in questo caso e fare per esso??? .. definire – Svisstack

+0

ho eseguito lo script sul mio server e collegato ad esso utilizzando SocketTest Quando stacco il client al server dà l'errorcode 104. Codice usato: '$ ErrorCode = socket_last_error(); $ ErrorMsg = socket_strerror ($ errorcode); morire ("Errore: (". $ Errorcode. ")". $ Errormsg. "\ N"); ' – onik

Problemi correlati