현재 위치: > 최신 기사 목록> socket_accept ()를 사용할 때 왜 갇히게됩니까? 차단 모드와 비 블로킹 모드의 차이점은 무엇입니까?

socket_accept ()를 사용할 때 왜 갇히게됩니까? 차단 모드와 비 블로킹 모드의 차이점은 무엇입니까?

M66 2025-05-20

네트워크 프로그래밍에 PHP를 사용할 때, 많은 개발자들은 socket_accept ()를 사용하여 TCP 서버를 만들 때 문제가 발생합니다. 프로그램이 고정되어 계속 실행할 수 없습니다. 이 현상은 주로 "차단 모드"및 "비 블로킹 모드"에 대한 이해가 충분하지 않습니다. 이 기사에서는 Socket_accept ()가 "고정"하는 이유를 설명하고 차단 모드와 비 블로킹 모드의 차이점을 자세히 설명합니다.

1. 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 ()가 클라이언트가 연결 될 때까지 연결을 기다리는 동안 계속 차단됩니다.

2. 왜 "고정"입니까?

소위 "Stuck"은 실제로 프로그램이 연결을 기다리고 있지만 반환되지는 않습니다. 이것은 버그가 아니라 차단 모드에서 정상적인 동작입니다.

기본적으로 PHP 소켓은 차단 모드에 있습니다. 이것은 다음을 의미합니다.

  • 클라이언트가 서버에 연결되어 있지 않으면 socket_accept ()가 대기합니다.

  • Socket_accept ()가 결과를 반환 할 때까지 CPU는 후속 코드를 실행하지 않습니다.

따라서 클라이언트 연결없이 서버를 디버깅하거나 실행할 때 프로그램은 항상 Socket_accept () 행에 "고정"됩니다.

서버는 연결을 기다려야하기 때문에 생산 환경에서는 허용됩니다. 그러나 디버깅 또는 여러 작업을 처리 해야하는 환경에서는이 차단 동작이 문제가 될 수 있습니다.

3. 비 차단 모드 용 솔루션

정기적으로 특정 작업을 수행하거나 다른 이벤트를 감지하는 등 연결없이 프로그램이 계속 실행되기를 원하시면 차단 모드를 사용해야합니다.

비 블로킹 모드 설정 :

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

4. Socket_Select ()를 사용하여 더 우아하게 차단을 관리하십시오

또 다른 일반적인 관행은 socket_select ()를 사용하여 읽고 쓸 수있는 소켓이 있는지 여부를 감지하는 것입니다.

 $read = [$socket];
$write = $except = null;

if (socket_select($read, $write, $except, 5) > 0) {
    $client = socket_accept($socket);
    // 클라이언트 연결을 처리합니다
}

시간 초과 시간을 설정할 수 있기 때문에이 방법은 무기한 차단되지 않습니다. 또한 여러 소켓이 동시에 듣는 장면에도 적합하며 고성능 네트워크 프로그래밍에서 일반적인 기술입니다.

5. 요약

  • socket_accept ()가 기본적으로 차단되고 있으며 연결 요청이 없으면 대기합니다.

  • 동작 차단은 버그가 아니지만 연결을 기다리는 동안 프로그램이 "정체"하게됩니다.

  • 프로그램 정체를 피하기 위해 Socket_set_nonBlock ()를 비 블로킹 모드로 설정할 수 있습니다.

  • 보다 고급 솔루션은 Socket_Select ()를 사용하여 여러 소켓의 상태를 관리하는 것입니다.