2016-06-20 5 views
0
ist

Ich habe die folgende Methode:Kann nicht zur Adresse binden, weil es den Einsatz bereits in

public static function listen(int $port, callable $callback) { 
     ob_implicit_flush(); 

     if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) { 
      println("socket_create() failed: reason: " . socket_strerror(socket_last_error())); 
     } 

     if (socket_bind($sock, '127.0.0.1', $port) === false) { 
      println("socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock))); 
     } 

     if (socket_listen($sock, 5) === false) { 
      println("socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock))); 
     } 

     if ($callback !== null && is_callable($callback)) { 
      call_user_func($callback); 
     } 

     do { 
      if (($msgsock = socket_accept($sock)) === false) { 
       println("socket_accept() failed: reason: " . socket_strerror(socket_last_error($sock))); 
       continue; 
      } 

      if (false === ($buf = socket_read($msgsock, 2048, PHP_BINARY_READ))) { 
       println("socket_read() failed: reason: " . socket_strerror(socket_last_error($msgsock))); 
       continue; 
      } 

      $eventName = trim(explode(' ', $buf)[1], '/'); 

      $msg = ''; 

      foreach (self::$events as $event) { 
       if ($event->name() == $eventName) { 
        $msg = $event->headers(); 
        $msg .= $event->run(); 
        break; 
       } 
      } 

      socket_write($msgsock, $msg, strlen($msg)); 
      socket_close($msgsock); 
      println("socket closed"); 
     } while (true); 

     socket_close($sock); 

    } 

Wenn ich es durch die Kommandozeile ausgeführt werden, es funktioniert gut. Wenn ich eine Seite in meinem Browser öffne und Inhalt vom Socket anfordere, gibt es die richtigen Header aus und zeigt den richtigen Inhalt auf der Seite an.

Wenn ich den Code bearbeiten, und drücken Sie den Code Strg + C und erneut ausführen, bekomme ich folgende Fehlermeldung:

PHP Warning: socket_bind(): unable to bind address [98]: Address already in use in /path/to/file.php on line 20 
socket_bind() failed: reason: Address already in use 

Dies macht es schwer, den Code zu aktualisieren, da ich warten müssen ein paar Augenblicke, bis ich den Code erneut ausführen kann. Gibt es eine Möglichkeit für mich, alle Steckdosen zu schließen, wenn Sie drücken Strg + C?

Ich habe festgestellt, dass ich den Prozess oft starten und stoppen kann, solange ich es nicht im Browser lade.

Antwort

1

Ich weiß nicht, PHP, aber im Allgemeinen müssen Sie einen Handler für das Signal SIGINT registrieren, und schließen Sie alle offenen Ressourcen in diesem Handler.

Bitte beachten Sie, dass, wenn Sie einen Handler für SIGINT registrieren, Ctrl-C den Prozess nicht mehr beenden wird (stattdessen wird der Handler ausgelöst), so dass der Signalhandler sicherstellen muss, dass das Programm beendet wird, wenn Sie das sind wollen.

dies Nach answer-How do I catch a KILL or HUP or User Abort signal?, Sie in PHP pcntl_signal verwenden sollten

bearbeiten ein Signal war zu registrieren: Offenbar Sie ticks für das Signal-Handler Feuer aktivieren. Ein kleines Beispiel:

declare(ticks=1); 

function sig_handler($signo) 
{ 
    switch ($signo) { 
     case SIGINT: 
      echo "Caught SIGINT, exiting.\n"; 
      exit; 
      break; 
     default: 
      // handle all other signals 
      echo "Caught signal $signo...\n"; 
    } 

} 

// setup signal handler 
pcntl_signal(SIGINT, 'sig_handler'); 

for ($x = 0; $x <= 50; $x++) { 
    echo "main loop: $x\n"; 
    sleep(1); 
} 

Der Wert für ticks ist ein Kompromiss zwischen der Ansprechbarkeit und Overhead.

+0

Ich dachte, ich müsste das tun, also habe ich versucht, einen hinzuzufügen, aber es führt den Rückruf nicht aus. Es stoppt jedoch die Aufhebung der Tastatureingabe. Ich stelle es direkt vor dem 'tun'. –

+0

aktualisierte Antwort mit Arbeitsbeispiel – drRobertz

+0

in Bezug auf Platzierung, würde ich vorschlagen, die Signal-Handler so früh wie möglich zu installieren. – drRobertz

Verwandte Themen