2016-06-20 4 views
0

이미 있기 때문에 해결하기 위해 결합 할 수 없습니다 나는 다음과 같은 방법이 있습니다 내가 명령 줄을 통해 그것을 실행하면는 사용

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); 

    } 

, 그것은 잘 작동합니다. 브라우저에서 페이지를 열고 소켓에서 컨텐츠를 요청하면 올바른 헤더가 출력되고 페이지에 올바른 컨텐츠가 표시됩니다. 내가 코드를 편집하고 Ctrl + C를 눌러 코드를 다시 실행

, 나는 다음과 같은 오류 얻을 : 나는 기다릴 필요로

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 

이, 그것은 하드 코드를 업데이트 할 수 있습니다를 내가 코드를 다시 실행할 수있을 때까지 잠시. Ctrl + C을 누르면 모든 소켓을 닫을 수 있습니까?

브라우저에서로드하지 않는 한 프로세스를 여러 번 시작하고 중지 할 수있는 것으로 나타났습니다.

답변

1

PHP를 모르지만 일반적으로 신호 SIGINT에 대한 핸들러를 등록하고 해당 핸들러의 열려있는 모든 리소스를 닫아야합니다.

SIGINT에 대한 핸들러를 등록하면 Ctrl-C가 더 이상 프로세스를 종료하지 않으며 (처리기를 트리거 함) 신호 처리기가 프로그램 종료를 확인해야합니다. 필요. 이 answerHow do I catch a KILL or HUP or User Abort signal?에 따르면

, 당신은 PHP에서 신호를 등록 pcntl_signal을했다 사용해야

편집 : 분명히, 당신은 화재에 대한 신호 처리기에 대한 ticks를 사용하도록 설정해야합니다. 작은 예 :

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); 
} 

ticks 값이 응답 오버 헤드 간의 절충이다.

+0

나는 그것을 할 필요가 있다고 생각했기 때문에 그것을 추가하려고 시도했지만 콜백을 실행하지 않는다. 그것은 키보드 입력의 취소를 비록 멈춘다. 나는 do 앞에 오기 전에 그것을 넣었다. –

+0

게재 위치에 대한 작업 예제 – drRobertz

+0

으로 업데이트 된 답변을 얻으려면 가능한 한 일찍 신호 처리기를 설치하는 것이 좋습니다. – drRobertz