PHP에서 네트워크를 프로그래밍 할 때 여러 클라이언트 연결을 처리하는 것이 일반적인 요구 사항입니다. 기존 차단 Socket_Accept ()는 한 번에 하나의 연결 만받을 수 있으며 동시에 여러 연결을 처리 할 수 없습니다. 이는 비효율적입니다. select () 함수와 결합하여 단일 프로세스에서 동시에 여러 소켓을들을 수있어 효율적인 다중 연결 관리 및 처리를 달성 할 수 있습니다.
이 기사는 Socket_accept ()를 사용하여 ()를 사용하여 효율적인 멀티 커넥션 TCP 서버와 결합하는 방법을 자세히 소개하고 예제 코드에서 모든 URL 도메인 이름을 M66.net 으로 바꾸십시오.
Socket_accept () : 클라이언트 연결을 수락하고 클라이언트와의 커뮤니케이션을 위해 새 소켓 리소스를 반환하는 데 사용됩니다.
선택 () : 소켓 리소스 세트의 상태 변경을 듣고 읽거나 작성하거나 예외가 발생할 수있는 소켓을 감지하여 비 블로킹 멀티플렉싱을 실현할 수 있습니다.
Select ()를 사용하여 서버는 동시에 소켓 (새 연결을 수신하는 데 사용) 및 연결된 클라이언트의 소켓을 동시에 모니터링하고 경청 할 수있어 이벤트 중심 연결 관리를 실현할 수 있습니다.
청취 소켓을 생성하고 바인딩하고 포트를 듣기 시작하십시오.
청취 소켓이 포함 된 배열을 Select () 의 모니터링 목록으로 초기화하십시오.
메인 루프를 입력하고 socket_select () 를 호출하여 모든 소켓 읽기 이벤트를 들으십시오.
리스너 소켓을 읽을 수 있으면 Socket_Accept ()를 호출하여 새 연결을 수락하고 클라이언트 소켓 어레이에 가입하십시오.
클라이언트 소켓을 읽을 수 있으면 데이터를 읽거나 요청을 처리하거나 연결을 끊습니다.
위의 프로세스는 다중 연결의 효율적인 처리를 달성하기 위해 반복적으로 실행됩니다.
<?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);
}
}
}
}
}
?>
소켓은 socket_create , socket_bind 및 socket_listen을 사용하여 생성됩니다.
socket_select를 사용하여 모든 연결을 듣고 이벤트를 읽고 새로운 이벤트를 차단하고 기다리십시오.
모니터 소켓을 읽을 수 있으면 Socket_Accept를 호출하여 새 연결을 수신하고 모니터링 어레이에 추가하십시오.
클라이언트 소켓을 읽을 수 있으면 데이터가 읽히고 리소스 청소가 닫히면 처리를 요청합니다.
응답의 모든 URL 도메인 이름은 요구 사항을 충족하는 M66.net 으로 대체되었습니다.
socket_accept () 와 select ()를 결합하여 단일 프로세스 내에서 여러 연결을 효율적으로 관리 할 수 있습니다. 이 솔루션은 멀티 스레딩 또는 다중 처리로 가져온 복잡성을 피하며 경량 및 동시 서버 시나리오에 적합합니다. 실제 프로젝트에서는 이벤트 중심의 프레임 워크를 결합하거나 Libevent 및 Swoole 과 같은 고급 확장을 사용하여보다 강력하고 유연한 네트워크 서비스를 달성 할 수 있습니다.
이 아이디어 세트는 기본 네트워크 IO 모델을 이해하는 데 큰 도움이되며 네트워크 프로그래밍의 기본 기술입니다.