라이브러리가 이벤트 I/O에 사용할 수 있는 ReactPHP의 핵심 리액터 이벤트 루프입니다.
개발 버전: 이 분기에는 향후 v3 릴리스에 대한 코드가 포함되어 있습니다. 현재 stable v1 릴리스의 코드는
1.x
분기를 확인하세요.다가오는 v3 릴리스는 이 패키지의 발전이 될 것입니다. 하지만 아직 최신 버전이 아닌 버전에 대해서는 v1을 적극적으로 지원할 예정입니다. 자세한 내용은 설치 지침을 참조하세요.
비동기 기반 라이브러리가 상호 운용 가능하려면 동일한 이벤트 루프를 사용해야 합니다. 이 구성 요소는 모든 라이브러리가 대상으로 삼을 수 있는 공통 LoopInterface
제공합니다. 이를 통해 사용자가 제어하는 단일 run()
호출을 통해 동일한 루프에서 사용할 수 있습니다.
목차
빠른 시작 예시
용법
달리다()
멈추다()
타이머 추가()
addPeriodicTimer()
취소타이머()
미래틱()
추가신호()
제거신호()
addReadStream()
addWriteStream()
제거ReadStream()
제거WriteStream()
스트림선택루프
ExtEventLoop
ExtEvLoop
ExtUvLoop
루프 방법
루프 자동 실행
얻다()
고리
루프 구현
루프 인터페이스
설치하다
테스트
특허
더
다음은 이벤트 루프만으로 구축된 비동기 HTTP 서버입니다.
<?phpuse ReactEventLoopLoop;require __DIR__ . '/vendor/autoload.php';$server = stream_socket_server('tcp://127.0.0.1:8080');stream_set_blocking($server, false); Loop::addReadStream($server, function ($server) {$conn = stream_socket_accept($server);$data = "HTTP/1.1 200 OKrnContent-Length: 3rnrnHin"; 루프::addWriteStream($conn, 함수 ($conn) 사용 (&$data) {$writer = fwrite($conn, $data);if ($writer === strlen($data)) {fclose($conn ); 루프::removeWriteStream($conn); } else {$data = substr($data, $write); } }); }); Loop::addPeriodicTimer(5, function () {$memory = memory_get_usage() / 1024;$formatted = number_format($memory, 3).'K';echo "현재 메모리 사용량: {$formatted}n"; });
예제도 참조하세요.
일반적인 응용 프로그램은 Loop
클래스를 사용하여 다음과 같이 기본 이벤트 루프를 사용합니다.
ReactEventLoopLoop 사용;$timer = Loop::addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; }); Loop::addTimer(1.0, function () 사용 ($timer) { 루프::cancelTimer($timer);echo '완료' . PHP_EOL; });
대안으로, 처음에 이벤트 루프 인스턴스를 명시적으로 생성하고 이를 프로그램 전체에서 재사용한 후 마지막으로 다음과 같이 프로그램 끝에서 실행할 수도 있습니다.
$loop = ReactEventLoopLoop::get();$timer = $loop->addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; });$loop->addTimer(1.0, function () use ($loop, $timer) {$loop->cancelTimer($timer);echo 'Done' . PHP_EOL; });$loop->run();
전자가 더 간결한 반면, 후자가 더 명확합니다. 두 경우 모두 프로그램은 정확히 동일한 단계를 수행합니다.
이벤트 루프 인스턴스는 프로그램 시작 부분에 생성됩니다. 이는 Loop
클래스를 처음 호출할 때(또는 루프 구현을 수동으로 인스턴스화하여) 암시적으로 수행됩니다.
이벤트 루프는 직접 사용되거나 라이브러리 및 애플리케이션 코드에 인스턴스로 전달됩니다. 이 예에서 주기 타이머는 다른 타이머가 1초 후에 주기 타이머를 중지할 때까지 매 초마다 Tick
출력하는 이벤트 루프에 등록됩니다.
이벤트 루프는 프로그램이 끝날 때 실행됩니다. 이는 Loop
클래스를 사용하거나 프로그램 끝에서 단일 run()
호출을 통해 명시적으로 수행될 때 자동으로 수행됩니다.
v1.2.0
부터는 Loop
클래스를 사용하는 것이 좋습니다. 명시적 루프 명령어는 여전히 유효하며 일부 응용 프로그램, 특히 보다 간결한 스타일로 전환하는 기간에 여전히 유용할 수 있습니다.
Loop
클래스는 이벤트 루프에 대한 편리한 전역 접근자로 존재합니다.
Loop
클래스는 LoopInterface
에 정적 메서드로 존재하는 모든 메서드를 제공합니다.
달리다()
멈추다()
타이머 추가()
addPeriodicTimer()
취소타이머()
미래틱()
추가신호()
제거신호()
addReadStream()
addWriteStream()
제거ReadStream()
제거WriteStream()
애플리케이션 코드에서 이벤트 루프로 작업하는 경우 다음과 같이 Loop
클래스에 정의된 정적 메서드와 직접 인터페이스하는 것이 가장 쉬운 경우가 많습니다.
ReactEventLoopLoop 사용;$timer = Loop::addPeriodicTimer(0.1, function () {echo 'Tick' . PHP_EOL; }); Loop::addTimer(1.0, function () 사용 ($timer) { 루프::cancelTimer($timer);echo '완료' . PHP_EOL; });
반면에 객체 지향 프로그래밍(OOP) 및 종속성 주입(DI)에 익숙하다면 다음과 같이 이벤트 루프 인스턴스를 삽입하고 LoopInterface
에서 인스턴스 메서드를 호출할 수 있습니다.
ReactEventLoopLoop 사용;ReactEventLoopLoopInterface 사용;Greeter 클래스 {개인 $loop;공용 함수 __construct(LoopInterface $loop) {$this->loop = $loop; }공개 함수 Greeting(string $name) {$this->loop->addTimer(1.0, function () use ($name) {echo 'Hello' . $name . '!' . PHP_EOL; }); } }$greeter = new Greeter(Loop::get());$greeter->greet('앨리스');$greeter->greet('Bob');
각 정적 메서드 호출은 내부적으로 Loop::get()
호출을 사용하여 기본 이벤트 루프 인스턴스에 있는 그대로 전달됩니다. 사용 가능한 메서드에 대한 자세한 내용은 LoopInterface
참조하세요.
Loop
클래스를 사용하면 프로그램이 끝날 때 루프가 자동으로 실행됩니다. 이는 다음 예제가 타이머를 예약하고 타이머 이벤트가 발생할 때까지 프로그램을 자동으로 실행함을 의미합니다.
ReactEventLoopLoop를 사용하세요. Loop::addTimer(1.0, function () {echo 'Hello' . PHP_EOL; });
v1.2.0
부터는 이러한 방식으로 Loop
클래스를 사용하고 명시적인 run()
호출을 생략하는 것이 좋습니다. BC 이유로 인해 명시적인 run()
메서드는 여전히 유효하며 일부 응용 프로그램, 특히 보다 간결한 스타일로 전환하는 기간 동안 여전히 유용할 수 있습니다.
Loop
자동으로 실행되는 것을 원하지 않으면 명시적으로 run()
또는 stop()
을 수행할 수 있습니다. 이는 다음과 같은 전역 예외 처리기를 사용하는 경우 유용할 수 있습니다.
ReactEventLoopLoop를 사용하세요. Loop::addTimer(10.0, function () {echo '절대로 발생하지 않음'; });set_Exception_handler(function (Throwable $e) {echo 'Error: ' . $e->getMessage() . PHP_EOL; 루프::중지(); });throw new RuntimeException('데모');
get(): LoopInterface
메소드는 현재 활성화된 이벤트 루프 인스턴스를 가져오는 데 사용할 수 있습니다.
이 메서드는 애플리케이션 수명 전체에 걸쳐 항상 동일한 이벤트 루프 인스턴스를 반환합니다.
ReactEventLoopLoop 사용; ReactEventLoopLoopInterface 사용;$loop = Loop::get();assert($loop instanceof LoopInterface);assert($loop === Loop::get());
이는 객체 지향 프로그래밍(OOP) 및 종속성 주입(DI)을 사용하는 경우 특히 유용합니다. 이 경우 이벤트 루프 인스턴스를 삽입하고 다음과 같이 LoopInterface
에서 인스턴스 메서드를 호출할 수 있습니다.
ReactEventLoopLoop 사용;ReactEventLoopLoopInterface 사용;Greeter 클래스 {개인 $loop;공용 함수 __construct(LoopInterface $loop) {$this->loop = $loop; }공개 함수 Greeting(string $name) {$this->loop->addTimer(1.0, function () use ($name) {echo 'Hello' . $name . '!' . PHP_EOL; }); } }$greeter = new Greeter(Loop::get());$greeter->greet('앨리스');$greeter->greet('Bob');
사용 가능한 메서드에 대한 자세한 내용은 LoopInterface
참조하세요.
LoopInterface
외에도 다양한 이벤트 루프 구현이 제공됩니다.
모든 이벤트 루프는 다음 기능을 지원합니다.
파일 설명자 폴링
일회용 타이머
주기적 타이머
향후 루프 틱에서 실행 지연
이 패키지의 대부분의 소비자에게 기본 이벤트 루프 구현은 구현 세부 사항입니다. 새 인스턴스를 자동으로 생성하려면 Loop
클래스를 사용해야 합니다.
고급의! 특정 이벤트 루프 구현이 명시적으로 필요한 경우 다음 클래스 중 하나를 수동으로 인스턴스화할 수 있습니다. 각 이벤트 루프 구현에 필요한 PHP 확장을 먼저 설치해야 할 수도 있습니다. 그렇지 않으면 생성 시 BadMethodCallException
이 발생합니다.
stream_select()
기반 이벤트 루프.
이것은 stream_select()
함수를 사용하며 PHP에서 즉시 작동하는 유일한 구현입니다.
이 이벤트 루프는 모든 PHP 버전에서 기본적으로 작동합니다. 즉, 설치가 필요하지 않으며 이 라이브러리는 모든 플랫폼과 지원되는 PHP 버전에서 작동합니다. 따라서 아래 나열된 이벤트 루프 확장을 설치하지 않으면 Loop
클래스는 기본적으로 이 이벤트 루프를 사용합니다.
내부적으로는 간단한 select
시스템 호출을 수행합니다. 이 시스템 호출은 FD_SETSIZE
(플랫폼에 따라 다름, 일반적으로 1024)의 최대 파일 설명자 수로 제한되며 O(m)
( m
전달된 최대 파일 설명자 수)로 확장됩니다. 이는 수천 개의 스트림을 동시에 처리할 때 문제가 발생할 수 있으며 이 경우 아래 나열된 대체 이벤트 루프 구현 중 하나를 사용하는 것을 고려할 수 있음을 의미합니다. 귀하의 사용 사례가 한 번에 수십 또는 수백 개의 스트림만 처리하는 것과 관련된 많은 일반적인 사용 사례 중 하나라면 이 이벤트 루프 구현은 정말 잘 수행됩니다.
신호 처리(아래 addSignal()
참조)를 사용하려면 이 이벤트 루프 구현에 ext-pcntl
필요합니다. 이 확장은 Unix 계열 플랫폼에서만 사용할 수 있으며 Windows는 지원하지 않습니다. 일반적으로 많은 PHP 배포판의 일부로 설치됩니다. 이 확장이 누락된 경우(또는 Windows에서 실행 중인 경우) 신호 처리가 지원되지 않으며 대신 BadMethodCallException
발생합니다.
이 이벤트 루프는 PHP 7.3 이전 버전을 사용할 때 향후 타이머를 예약하기 위해 벽시계 시간에 의존하는 것으로 알려져 있습니다. 단조로운 시간 소스는 PHP 7.3( hrtime()
)에서만 사용할 수 있기 때문입니다. 이는 많은 일반적인 사용 사례에 영향을 미치지 않지만 높은 시간 정밀도에 의존하는 프로그램이나 불연속적인 시간 조정(시간 점프)이 적용되는 시스템의 경우 중요한 차이점입니다. 즉, PHP < 7.3에서 타이머가 30초 후에 실행되도록 예약한 다음 시스템 시간을 20초 앞으로 조정하면 타이머가 10초 후에 실행될 수 있습니다. 자세한 내용은 addTimer()
참조하세요.
ext-event
기반 이벤트 루프.
이는 libevent
라이브러리에 대한 인터페이스를 제공하는 event
PECL 확장을 사용합니다. libevent
자체는 다양한 시스템별 백엔드(epoll, kqueue)를 지원합니다.
이 루프는 PHP 7.1부터 PHP 8+까지 작동하는 것으로 알려져 있습니다.
ext-ev
기반 이벤트 루프.
이 루프는 libev
라이브러리에 대한 인터페이스를 제공하는 ev
PECL 확장을 사용합니다. libev
자체는 다양한 시스템별 백엔드(epoll, kqueue)를 지원합니다.
이 루프는 PHP 7.1부터 PHP 8+까지 작동하는 것으로 알려져 있습니다.
ext-uv
기반 이벤트 루프.
이 루프는 libuv
라이브러리에 대한 인터페이스를 제공하는 uv
PECL 확장을 사용합니다. libuv
자체는 다양한 시스템별 백엔드(epoll, kqueue)를 지원합니다.
이 루프는 PHP 7.1부터 PHP 8+까지 작동하는 것으로 알려져 있습니다.
run(): void
메소드를 사용하면 더 이상 수행할 작업이 없을 때까지 이벤트 루프를 실행할 수 있습니다.
많은 애플리케이션에서 이 메서드는 이벤트 루프에서 직접적으로 표시되는 유일한 호출입니다. 경험상 일반적으로 모든 것을 동일한 루프 인스턴스에 연결한 다음 애플리케이션 하단에서 루프를 한 번 실행하는 것이 좋습니다.
$loop->run();
이 방법은 더 이상 수행할 작업이 없을 때까지 루프를 계속 실행합니다. 즉, 이 메서드는 마지막 타이머, 스트림 및/또는 신호가 제거될 때까지 차단됩니다.
마찬가지로 애플리케이션이 실제로 이 메서드를 한 번 호출하는지 확인하는 것이 중요합니다. 루프에 리스너를 추가하고 실제로 실행하지 않으면 연결된 리스너를 실제로 기다리지 않고 애플리케이션이 종료됩니다.
루프가 이미 실행 중인 동안에는 이 메서드를 호출하면 안 됩니다. 이 메소드는 명시적으로 stop()
이 실행된 후 또는 이전에 더 이상 수행할 작업이 없었기 때문에 자동으로 중지된 후에 두 번 이상 호출될 수 있습니다.
stop(): void
메소드는 실행 중인 이벤트 루프에 중지를 지시하는 데 사용할 수 있습니다.
이 방법은 고급 사용법으로 간주되므로 주의해서 사용해야 합니다. 경험상, 더 이상 할 일이 없을 때만 루프가 자동으로 중지되도록 하는 것이 일반적으로 권장됩니다.
이 메서드를 사용하여 이벤트 루프에 중지를 명시적으로 지시할 수 있습니다.
$loop->addTimer(3.0, function () use ($loop) {$loop->stop(); });
현재 실행 중이 아닌 루프 인스턴스 또는 이미 중지된 루프 인스턴스에서 이 메서드를 호출해도 아무런 효과가 없습니다.
addTimer(float $interval, callable $callback): TimerInterface
메소드를 사용하면 지정된 간격 후에 한 번 호출되도록 콜백을 대기열에 추가할 수 있습니다.
두 번째 매개변수는 타이머 인스턴스를 유일한 매개변수로 받아들이는 타이머 콜백 함수여야 합니다. 타이머 콜백 함수 내에서 타이머 인스턴스를 사용하지 않는다면 매개변수가 전혀 없는 함수를 사용할 수도 있습니다.
타이머 콜백 함수는 Exception
발생시켜서는 안 됩니다. 타이머 콜백 함수의 반환 값은 무시되고 아무런 영향을 미치지 않으므로 성능상의 이유로 과도한 데이터 구조를 반환하지 않는 것이 좋습니다.
이 메소드는 타이머 인스턴스를 반환합니다. 위에서 설명한 대로 동일한 타이머 인스턴스가 타이머 콜백 함수에도 전달됩니다. cancelTimer
호출하여 보류 중인 타이머를 취소할 수 있습니다. addPeriodicTimer()
와 달리 이 메서드는 콜백이 지정된 간격 후에 한 번만 호출되도록 보장합니다.
$loop->addTimer(0.8, function () {echo 'world!' . PHP_EOL; });$loop->addTimer(0.3, function () {echo 'hello'; });
예제 #1도 참조하세요.
콜백 함수 내의 변수에 액세스하려면 다음과 같이 임의의 데이터를 콜백 클로저에 바인딩할 수 있습니다.
함수 hello($name, LoopInterface $loop) {$loop->addTimer(1.0, function () use ($name) {echo "hello $namen"; }); }hello('테스터', $loop);
이 인터페이스는 특정 타이머 확인을 강제하지 않으므로 밀리초 이하의 매우 높은 정밀도에 의존하는 경우 특별한 주의가 필요할 수 있습니다. 이벤트 루프 구현은 최선을 다해 작동해야 하며 달리 명시되지 않는 한 최소 밀리초의 정확도를 제공해야 합니다(SHOULD). 기존의 많은 이벤트 루프 구현은 마이크로초 정확도를 제공하는 것으로 알려져 있지만 일반적으로 이러한 높은 정밀도에 의존하는 것은 권장되지 않습니다.
마찬가지로, 동시에 실행되도록 예약된 타이머의 실행 순서(가능한 정확도 내에서)는 보장되지 않습니다.
이 인터페이스는 이벤트 루프 구현이 가능한 경우 단조로운 시간 소스를 사용해야 한다고 제안합니다. 단조로운 시간 소스는 기본적으로 PHP 7.3부터만 사용할 수 있으므로 이벤트 루프 구현은 벽시계 시간을 사용하도록 대체될 수 있습니다. 이는 많은 일반적인 사용 사례에 영향을 미치지 않지만 높은 시간 정밀도에 의존하는 프로그램이나 불연속적인 시간 조정(시간 점프)이 적용되는 시스템의 경우 중요한 차이점입니다. 즉, 타이머가 30초 후에 실행되도록 예약한 다음 시스템 시간을 20초 앞으로 조정하면 타이머는 여전히 30초 후에 실행되어야 합니다. 자세한 내용은 이벤트 루프 구현을 참조하세요.
addPeriodicTimer(float $interval, callable $callback): TimerInterface
메소드를 사용하여 지정된 간격 후에 반복적으로 호출되도록 콜백을 대기열에 넣을 수 있습니다.
두 번째 매개변수는 타이머 인스턴스를 유일한 매개변수로 받아들이는 타이머 콜백 함수여야 합니다. 타이머 콜백 함수 내에서 타이머 인스턴스를 사용하지 않는다면 매개변수가 전혀 없는 함수를 사용할 수도 있습니다.
타이머 콜백 함수는 Exception
발생시켜서는 안 됩니다. 타이머 콜백 함수의 반환 값은 무시되고 아무런 영향을 미치지 않으므로 성능상의 이유로 과도한 데이터 구조를 반환하지 않는 것이 좋습니다.
이 메소드는 타이머 인스턴스를 반환합니다. 위에서 설명한 대로 동일한 타이머 인스턴스가 타이머 콜백 함수에도 전달됩니다. addTimer()
와 달리 이 메서드는 지정된 간격 이후 또는 cancelTimer
호출할 때까지 콜백이 무한히 호출되도록 합니다.
$timer = $loop->addPeriodicTimer(0.1, function () {echo 'tick!' . PHP_EOL; });$loop->addTimer(1.0, function () use ($loop, $timer) {$loop->cancelTimer($timer);echo 'Done' . PHP_EOL; });
예제 #2도 참조하세요.
실행 횟수를 제한하려면 다음과 같이 임의의 데이터를 콜백 클로저에 바인딩할 수 있습니다.
함수 hello($name, LoopInterface $loop) {$n = 3;$loop->addPeriodicTimer(1.0, 함수 ($timer) 사용 ($name, $loop, &$n) {if ($n > 0) { --$n;echo "안녕하세요 $namen"; } else {$loop->cancelTimer($timer); } }); }hello('테스터', $loop);
이 인터페이스는 특정 타이머 확인을 강제하지 않으므로 밀리초 이하의 매우 높은 정밀도에 의존하는 경우 특별한 주의가 필요할 수 있습니다. 이벤트 루프 구현은 최선을 다해 작동해야 하며 달리 명시되지 않는 한 최소 밀리초의 정확도를 제공해야 합니다(SHOULD). 기존의 많은 이벤트 루프 구현은 마이크로초 정확도를 제공하는 것으로 알려져 있지만 일반적으로 이러한 높은 정밀도에 의존하는 것은 권장되지 않습니다.
마찬가지로, 동시에 실행되도록 예약된 타이머의 실행 순서(가능한 정확도 내에서)는 보장되지 않습니다.
이 인터페이스는 이벤트 루프 구현이 가능한 경우 단조로운 시간 소스를 사용해야 한다고 제안합니다. 단조로운 시간 소스는 기본적으로 PHP 7.3부터만 사용할 수 있으므로 이벤트 루프 구현은 벽시계 시간을 사용하도록 대체될 수 있습니다. 이는 많은 일반적인 사용 사례에 영향을 미치지 않지만 높은 시간 정밀도에 의존하는 프로그램이나 불연속적인 시간 조정(시간 점프)이 적용되는 시스템의 경우 중요한 차이점입니다. 즉, 타이머가 30초 후에 실행되도록 예약한 다음 시스템 시간을 20초 앞으로 조정하면 타이머는 여전히 30초 후에 실행되어야 합니다. 자세한 내용은 이벤트 루프 구현을 참조하세요.
또한 주기적 타이머는 호출할 때마다 일정을 다시 조정하기 때문에 타이머 드리프트가 발생할 수 있습니다. 따라서 일반적으로 밀리초 이하의 정확도를 갖는 고정밀 간격에 대해서는 이 방법을 사용하지 않는 것이 좋습니다.
cancelTimer(TimerInterface $timer): void
메소드를 사용하여 보류 중인 타이머를 취소할 수 있습니다.
addPeriodicTimer()
및 예제 #2도 참조하세요.
이 루프 인스턴스에 추가되지 않은 타이머 인스턴스 또는 이미 취소된 타이머에서 이 메서드를 호출해도 아무런 효과가 없습니다.
futureTick(callable $listener): void
메소드를 사용하면 이벤트 루프의 향후 틱에서 콜백이 호출되도록 예약할 수 있습니다.
이는 간격이 0초인 타이머와 매우 유사하게 작동하지만 타이머 대기열을 예약하는 오버헤드가 필요하지 않습니다.
틱 콜백 함수는 반드시 0개의 매개변수를 허용할 수 있어야 합니다.
틱 콜백 함수는 Exception
발생시켜서는 안 됩니다. 틱 콜백 함수의 반환 값은 무시되고 아무런 효과가 없으므로 성능상의 이유로 과도한 데이터 구조를 반환하지 않는 것이 좋습니다.
콜백 함수 내의 변수에 액세스하려면 다음과 같이 임의의 데이터를 콜백 클로저에 바인딩할 수 있습니다.
함수 hello($name, LoopInterface $loop) {$loop->futureTick(function () use ($name) {echo "hello $namen"; }); }hello('테스터', $loop);
타이머와 달리 틱 콜백은 대기열에 추가된 순서대로 실행되도록 보장됩니다. 또한 콜백이 대기열에 추가되면 이 작업을 취소할 수 있는 방법이 없습니다.
이는 더 큰 작업을 더 작은 단계(협력적 멀티태스킹의 한 형태)로 나누는 데 종종 사용됩니다.
$loop->futureTick(function () {echo 'b'; });$loop->futureTick(function () {echo 'c'; });에코 'a';
예제 #3도 참조하세요.
addSignal(int $signal, callable $listener): void
메소드를 사용하면 이 프로세스에서 신호를 포착할 때 알림을 받을 리스너를 등록할 수 있습니다.
이는 supervisor
또는 systemd
와 같은 도구에서 사용자 인터럽트 신호 또는 종료 신호를 포착하는 데 유용합니다.
두 번째 매개변수는 신호를 유일한 매개변수로 받아들이는 리스너 콜백 함수여야 합니다. 리스너 콜백 함수 내에서 신호를 사용하지 않는 경우 매개변수가 전혀 없는 함수를 사용할 수도 있습니다.
리스너 콜백 함수는 Exception
발생시켜서는 안 됩니다. 리스너 콜백 함수의 반환 값은 무시되고 아무런 영향을 미치지 않으므로 성능상의 이유로 과도한 데이터 구조를 반환하지 않는 것이 좋습니다.
$loop->addSignal(SIGINT, function (int $signal) {echo '사용자 인터럽트 신호를 포착했습니다' . PHP_EOL; });
예제 #4도 참조하세요.
신호는 Unix 계열 플랫폼에서만 사용할 수 있으며 Windows는 운영 체제 제한으로 인해 지원되지 않습니다. 이 플랫폼에서 신호가 지원되지 않는 경우(예: 필수 확장이 누락된 경우) 이 메서드는 BadMethodCallException
을 발생시킬 수 있습니다.
참고: 리스너는 동일한 신호에 한 번만 추가할 수 있으며, 두 번 이상 추가하려는 시도는 무시됩니다.
removeSignal(int $signal, callable $listener): void
메소드를 사용하면 이전에 추가된 신호 리스너를 제거할 수 있습니다.
$loop->removeSignal(SIGINT, $listener);
등록되지 않은 리스너를 제거하려는 모든 시도는 무시됩니다.
고급의! 이 하위 수준 API는 고급 사용으로 간주됩니다. 대부분의 사용 사례에서는 대신 읽을 수 있는 더 높은 수준의 Stream API를 사용해야 합니다.
addReadStream(resource $stream, callable $callback): void
메소드를 사용하면 스트림을 읽을 준비가 되었을 때 알림을 받을 리스너를 등록할 수 있습니다.
첫 번째 매개변수는 이 루프 구현으로 읽을 준비가 되었는지 확인을 지원하는 유효한 스트림 리소스여야 합니다. 단일 스트림 리소스를 두 번 이상 추가해서는 안 됩니다. 대신, 먼저 removeReadStream()
호출하거나 단일 리스너로 이 이벤트에 반응한 다음 이 리스너에서 전달하십시오. 이 메소드는 주어진 자원 유형이 이 루프 구현에서 지원되지 않는 경우 Exception
발생시킬 수 있습니다.
두 번째 매개변수는 스트림 리소스를 유일한 매개변수로 받아들이는 리스너 콜백 함수여야 합니다. 리스너 콜백 함수 내에서 스트림 리소스를 사용하지 않는 경우 매개변수가 전혀 없는 함수를 사용할 수도 있습니다.
리스너 콜백 함수는 Exception
발생시켜서는 안 됩니다. 리스너 콜백 함수의 반환 값은 무시되고 아무런 영향을 미치지 않으므로 성능상의 이유로 과도한 데이터 구조를 반환하지 않는 것이 좋습니다.
콜백 함수 내의 변수에 액세스하려면 다음과 같이 임의의 데이터를 콜백 클로저에 바인딩할 수 있습니다.
$loop->addReadStream($stream, 함수 ($stream) 사용 ($name) {echo $name . ' 말했다: ' . fread($stream); });
예제 #11도 참조하세요.
removeReadStream()
호출하여 이 스트림에 대한 읽기 이벤트 리스너를 제거할 수 있습니다.
여러 스트림이 동시에 준비될 때 리스너의 실행 순서는 보장되지 않습니다.
일부 이벤트 루프 구현은 스트림을 읽을 수 있는 경우(에지 트리거)에만 리스너를 트리거하고 스트림을 처음부터 이미 읽을 수 있는 경우에는 트리거하지 않을 수 있는 것으로 알려져 있습니다. 이는 또한 데이터가 PHP의 내부 스트림 버퍼에 남아 있으면 스트림을 읽을 수 있는 것으로 인식하지 못할 수도 있음을 의미합니다. 따라서 stream_set_read_buffer($stream, 0);
사용하는 것이 좋습니다. 이 경우 PHP의 내부 읽기 버퍼를 비활성화합니다.
고급의! 이 하위 수준 API는 고급 사용으로 간주됩니다. 대부분의 사용 사례에서는 대신 더 높은 수준의 쓰기 가능한 Stream API를 사용해야 합니다.
addWriteStream(resource $stream, callable $callback): void
메소드를 사용하면 스트림이 쓸 준비가 되었을 때 알림을 받을 리스너를 등록할 수 있습니다.
첫 번째 매개변수는 이 루프 구현으로 쓸 준비가 되었는지 확인을 지원하는 유효한 스트림 리소스여야 합니다. 단일 스트림 리소스를 두 번 이상 추가해서는 안 됩니다. 대신, 먼저 removeWriteStream()
호출하거나 단일 리스너로 이 이벤트에 반응한 다음 이 리스너에서 전달하십시오. 이 메소드는 주어진 자원 유형이 이 루프 구현에서 지원되지 않는 경우 Exception
발생시킬 수 있습니다.
두 번째 매개변수는 스트림 리소스를 유일한 매개변수로 받아들이는 리스너 콜백 함수여야 합니다. 리스너 콜백 함수 내에서 스트림 리소스를 사용하지 않는 경우 매개변수가 전혀 없는 함수를 사용할 수도 있습니다.
리스너 콜백 함수는 Exception
발생시켜서는 안 됩니다. 리스너 콜백 함수의 반환 값은 무시되고 아무런 영향을 미치지 않으므로 성능상의 이유로 과도한 데이터 구조를 반환하지 않는 것이 좋습니다.
콜백 함수 내의 변수에 액세스하려면 다음과 같이 임의의 데이터를 콜백 클로저에 바인딩할 수 있습니다.
$loop->addWriteStream($stream, 함수($stream) 사용($name) {fwrite($stream, 'Hello' . $name); });
예제 #12도 참조하세요.
removeWriteStream()
호출하여 이 스트림에 대한 쓰기 이벤트 리스너를 제거할 수 있습니다.
여러 스트림이 동시에 준비될 때 리스너의 실행 순서는 보장되지 않습니다.
removeReadStream(resource $stream): void
메소드를 사용하면 해당 스트림에 대한 읽기 이벤트 리스너를 제거할 수 있습니다.
이미 제거된 루프에서 스트림을 제거하거나 추가된 적이 없거나 유효하지 않은 스트림을 제거하려고 해도 아무런 효과가 없습니다.
removeWriteStream(resource $stream): void
메소드를 사용하여 지정된 스트림에 대한 쓰기 이벤트 리스너를 제거할 수 있습니다.
이미 제거된 루프에서 스트림을 제거하거나 추가된 적이 없거나 유효하지 않은 스트림을 제거하려고 해도 아무런 효과가 없습니다.
이 라이브러리를 설치하는 권장 방법은 Composer를 사용하는 것입니다. Composer를 처음 사용하시나요?
일단 출시되면 이 프로젝트는 SemVer를 따릅니다. 현재로서는 최신 개발 버전이 설치됩니다.
작곡가는 반응/이벤트 루프가 필요합니다:^3@dev
버전 업그레이드에 대한 자세한 내용은 CHANGELOG를 참조하세요.
이 프로젝트는 모든 플랫폼에서 실행되는 것을 목표로 하므로 PHP 확장이 필요하지 않으며 PHP 7.1부터 현재 PHP 8+까지의 실행을 지원합니다. 이 프로젝트에는 지원되는 최신 PHP 버전을 사용하는 것이 좋습니다 .
이벤트 루프 확장을 설치하는 것이 권장되지만 전적으로 선택 사항입니다. 자세한 내용은 이벤트 루프 구현을 참조하세요.
테스트 스위트를 실행하려면 먼저 이 저장소를 복제한 다음 Composer를 통해 모든 종속성을 설치해야 합니다.
작곡가 설치
테스트 스위트를 실행하려면 프로젝트 루트로 이동하여 다음을 실행하십시오.
벤더/bin/phpunit
MIT, LICENSE 파일을 참조하세요.
실제 애플리케이션에서 스트림이 사용되는 방법에 대한 자세한 내용은 스트림 구성 요소를 참조하세요.
실제 애플리케이션에서 EventLoop를 사용하는 패키지 목록은 사용자 위키와 Packagist의 종속 항목을 참조하세요.