네트워크 프로그래밍에 PHP를 사용할 때, 많은 개발자들은 socket_accept ()를 사용하여 TCP 서버를 만들 때 문제가 발생합니다. 프로그램이 고정되어 계속 실행할 수 없습니다. 이 현상은 주로 "차단 모드"및 "비 블로킹 모드"에 대한 이해가 충분하지 않습니다. 이 기사에서는 Socket_accept ()가 "고정"하는 이유를 설명하고 차단 모드와 비 블로킹 모드의 차이점을 자세히 설명합니다.
Socket_accept () 는 PHP 소켓 확장에서 클라이언트의 연결 요청을 허용하는 기능입니다. socket_create () 로 소켓을 생성하고 socket_bind () 및 socket_listen ()을 사용하여 청취를 시작하려면 socket_accept ()를 사용하려면 연결을 받어야합니다.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8080);
socket_listen($socket);
while (true) {
$client = socket_accept($socket);
// 오른쪽 $client 읽기 및 쓰기 작업을 수행하십시오
}
위의 예에서는 Socket_accept ()가 클라이언트가 연결 될 때까지 연결을 기다리는 동안 계속 차단됩니다.
소위 "Stuck"은 실제로 프로그램이 연결을 기다리고 있지만 반환되지는 않습니다. 이것은 버그가 아니라 차단 모드에서 정상적인 동작입니다.
기본적으로 PHP 소켓은 차단 모드에 있습니다. 이것은 다음을 의미합니다.
클라이언트가 서버에 연결되어 있지 않으면 socket_accept ()가 대기합니다.
Socket_accept ()가 결과를 반환 할 때까지 CPU는 후속 코드를 실행하지 않습니다.
따라서 클라이언트 연결없이 서버를 디버깅하거나 실행할 때 프로그램은 항상 Socket_accept () 행에 "고정"됩니다.
서버는 연결을 기다려야하기 때문에 생산 환경에서는 허용됩니다. 그러나 디버깅 또는 여러 작업을 처리 해야하는 환경에서는이 차단 동작이 문제가 될 수 있습니다.
정기적으로 특정 작업을 수행하거나 다른 이벤트를 감지하는 등 연결없이 프로그램이 계속 실행되기를 원하시면 차단 모드를 사용해야합니다.
socket_set_nonblock($socket);
현재 Socket_accept ()는 더 이상 대기하지 않고 대신 :
연결이있을 때 클라이언트 소켓으로 돌아갑니다.
연결이 없을 때 즉시 False를 반환하고 오류 코드를 Socket_eagain 또는 Socket_ewouldBlock 으로 설정하십시오.
샘플 코드 :
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8080);
socket_listen($socket);
socket_set_nonblock($socket);
while (true) {
$client = @socket_accept($socket);
if ($client === false) {
// 연결 없음,다른 일을 계속하십시오
echo "연결을 기다리고 있습니다...\n";
sleep(1);
} else {
// 연결을 성공적으로 받았습니다
socket_write($client, "Hello from m66.net\n");
socket_close($client);
}
}
또 다른 일반적인 관행은 socket_select ()를 사용하여 읽고 쓸 수있는 소켓이 있는지 여부를 감지하는 것입니다.
$read = [$socket];
$write = $except = null;
if (socket_select($read, $write, $except, 5) > 0) {
$client = socket_accept($socket);
// 클라이언트 연결을 처리합니다
}
시간 초과 시간을 설정할 수 있기 때문에이 방법은 무기한 차단되지 않습니다. 또한 여러 소켓이 동시에 듣는 장면에도 적합하며 고성능 네트워크 프로그래밍에서 일반적인 기술입니다.
socket_accept ()가 기본적으로 차단되고 있으며 연결 요청이 없으면 대기합니다.
동작 차단은 버그가 아니지만 연결을 기다리는 동안 프로그램이 "정체"하게됩니다.
프로그램 정체를 피하기 위해 Socket_set_nonBlock ()를 비 블로킹 모드로 설정할 수 있습니다.
보다 고급 솔루션은 Socket_Select ()를 사용하여 여러 소켓의 상태를 관리하는 것입니다.