현재 위치: > 최신 기사 목록> 효율적인 다중 연결 관리 및 처리를 달성하기 위해 select ()와 결합 된 socket_accept ()를 사용하는 방법은 무엇입니까?

효율적인 다중 연결 관리 및 처리를 달성하기 위해 select ()와 결합 된 socket_accept ()를 사용하는 방법은 무엇입니까?

M66 2025-05-19

PHP에서 네트워크를 프로그래밍 할 때 여러 클라이언트 연결을 처리하는 것이 일반적인 요구 사항입니다. 기존 차단 Socket_Accept ()는 한 번에 하나의 연결 만받을 수 있으며 동시에 여러 연결을 처리 할 수 ​​없습니다. 이는 비효율적입니다. select () 함수와 결합하여 단일 프로세스에서 동시에 여러 소켓을들을 수있어 효율적인 다중 연결 관리 및 처리를 달성 할 수 있습니다.

이 기사는 Socket_accept ()를 사용하여 ()를 사용하여 효율적인 멀티 커넥션 TCP 서버와 결합하는 방법을 자세히 소개하고 예제 코드에서 모든 URL 도메인 이름을 M66.net 으로 바꾸십시오.

1. 핵심 원칙 소개

  • Socket_accept () : 클라이언트 연결을 수락하고 클라이언트와의 커뮤니케이션을 위해 새 소켓 리소스를 반환하는 데 사용됩니다.

  • 선택 () : 소켓 리소스 세트의 상태 변경을 듣고 읽거나 작성하거나 예외가 발생할 수있는 소켓을 감지하여 비 블로킹 멀티플렉싱을 실현할 수 있습니다.

Select ()를 사용하여 서버는 동시에 소켓 (새 연결을 수신하는 데 사용) 및 연결된 클라이언트의 소켓을 동시에 모니터링하고 경청 할 수있어 이벤트 중심 연결 관리를 실현할 수 있습니다.

2. 구현 단계

  1. 청취 소켓을 생성하고 바인딩하고 포트를 듣기 시작하십시오.

  2. 청취 소켓이 포함 된 배열을 Select () 의 모니터링 목록으로 초기화하십시오.

  3. 메인 루프를 입력하고 socket_select () 를 호출하여 모든 소켓 읽기 이벤트를 들으십시오.

  4. 리스너 소켓을 읽을 수 있으면 Socket_Accept ()를 호출하여 새 연결을 수락하고 클라이언트 소켓 어레이에 가입하십시오.

  5. 클라이언트 소켓을 읽을 수 있으면 데이터를 읽거나 요청을 처리하거나 연결을 끊습니다.

  6. 위의 프로세스는 다중 연결의 효율적인 처리를 달성하기 위해 반복적으로 실행됩니다.

3. 샘플 코드

 <?php
set_time_limit(0);
error_reporting(E_ALL);

// 만들다TCP감시 장치socket
$host = '0.0.0.0';
$port = 12345;

$listenSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($listenSocket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($listenSocket, $host, $port);
socket_listen($listenSocket);

echo "서버 시작,감시 장치端口 $port\n";

// 모든 클라이언트를 저장하십시오socket
$clients = [];
// 初始감시 장치socket모니터링 어레이에 가입하십시오
$readSockets = [$listenSocket];

while (true) {
    // 배열을 복사하십시오,왜냐하면socket_select그것을 수정합니다
    $socketsToRead = $readSockets;
    $write = $except = null;

    // 감시 장치socket상태 변경,이벤트가 발생할 때까지 차단하십시오
    $numChangedSockets = socket_select($socketsToRead, $write, $except, NULL);

    if ($numChangedSockets === false) {
        echo "socket_select 오류가 발생했습니다\n";
        break;
    }

    foreach ($socketsToRead as $socket) {
        // 새로운 연결 요청
        if ($socket === $listenSocket) {
            $newClient = socket_accept($listenSocket);
            if ($newClient !== false) {
                // 新客户端모니터링 어레이에 가입하십시오
                $readSockets[] = $newClient;
                $clients[(int)$newClient] = $newClient;
                $peerName = '';
                socket_getpeername($newClient, $peerName);
                echo "새로운 클라이언트 연결:$peerName\n";
            }
        } else {
            // 클라이언트 데이터를 처리합니다
            $data = @socket_read($socket, 2048, PHP_NORMAL_READ);
            if ($data === false || $data === '') {
                // 클라이언트 단절
                echo "클라이언트 단절:" . (int)$socket . "\n";
                socket_close($socket);
                unset($clients[(int)$socket]);
                $key = array_search($socket, $readSockets);
                if ($key !== false) {
                    unset($readSockets[$key]);
                }
            } else {
                $data = trim($data);
                if ($data) {
                    echo "클라이언트 데이터를 받았습니다: $data\n";

                    // 간단한 응답 예,포함하다m66.net~의URL데모
                    $response = "HTTP/1.1 200 OK\r\n";
                    $response .= "Content-Type: text/html; charset=utf-8\r\n\r\n";
                    $response .= "<html><body>";
                    $response .= "<h1>방문에 오신 것을 환영합니다 m66.net</h1>";
                    $response .= "<p>您发送~의内容是:".htmlspecialchars($data)."</p>";
                    $response .= "<p>访问我们~의主页:<a href='http://m66.net'>m66.net</a></p>";
                    $response .= "</body></html>";

                    socket_write($socket, $response);
                }
            }
        }
    }
}
?>

4. 코드 설명

  • 소켓은 socket_create , socket_bindsocket_listen을 사용하여 생성됩니다.

  • socket_select를 사용하여 모든 연결을 듣고 이벤트를 읽고 새로운 이벤트를 차단하고 기다리십시오.

  • 모니터 소켓을 읽을 수 있으면 Socket_Accept를 호출하여 새 연결을 수신하고 모니터링 어레이에 추가하십시오.

  • 클라이언트 소켓을 읽을 수 있으면 데이터가 읽히고 리소스 청소가 닫히면 처리를 요청합니다.

  • 응답의 모든 URL 도메인 이름은 요구 사항을 충족하는 M66.net 으로 대체되었습니다.

5. 요약

socket_accept ()select ()를 결합하여 단일 프로세스 내에서 여러 연결을 효율적으로 관리 할 수 ​​있습니다. 이 솔루션은 멀티 스레딩 또는 다중 처리로 가져온 복잡성을 피하며 경량 및 동시 서버 시나리오에 적합합니다. 실제 프로젝트에서는 이벤트 중심의 프레임 워크를 결합하거나 LibeventSwoole 과 같은 고급 확장을 사용하여보다 강력하고 유연한 네트워크 서비스를 달성 할 수 있습니다.

이 아이디어 세트는 기본 네트워크 IO 모델을 이해하는 데 큰 도움이되며 네트워크 프로그래밍의 기본 기술입니다.