PHP 네트워크 프로그래밍에서 stream_socket_shutdown 함수는 소켓 연결의 특정 방향 (읽기, 쓰기 또는 둘 다)을 닫는 데 사용됩니다. 그러나 실제로 사용하면 많은 개발자가 stream_socket_shutdown을 호출 한 후 비정상적인 연결 중단, 클라이언트 오류 및 데이터 손실과 같은 문제를 겪습니다. 이 기사는 Stream_Socket_Shutdown 의 작동 메커니즘을 깊이 분석하고 연결 예외의 원인을 탐색하며 피하고 수리하는 방법을 제공합니다.
stream_socket_shutdown 의 함수 정의는 다음과 같습니다.
bool stream_socket_shutdown(resource $stream, int $how)
$ stream : 오픈 소켓 스트림 리소스.
$ 방법 : 방향을 닫고 가치를 가져옵니다.
stream_shut_rd (0) 읽기 방향을 닫습니다
stream_shut_wr (1) 쓰기 방향을 닫습니다
stream_shut_rdwr (2) 읽기 및 쓰기 방향을 끄십시오
예를 들어:
$socket = stream_socket_client("tcp://m66.net:8080", $errno, $errstr, 30);
if (!$socket) {
die("연결이 실패했습니다: $errstr ($errno)");
}
// 글쓰기 방향을 닫습니다,데이터가 더 이상 전송되지 않음을 나타냅니다
stream_socket_shutdown($socket, STREAM_SHUT_WR);
stream_socket_shutdown을 호출 한 후 소켓의 특정 방향이 닫히고 커널은 핀 패킷을 피어에게 전송하여 연결이 닫혀 있음을 나타냅니다.
예외의 근본 원인은 stream_socket_shutdown을 사용할 때 클라이언트 또는 서버가 연결의 종료 신호를 올바르게 처리하지 않거나 마감 순서가 부적절하다는 것입니다. 구체적으로 다음과 같이 나타납니다.
쓰기 방향을 미리 닫아 피어가 데이터 읽기를 마치지 않으면 연결을 연결 해제합니다.
동시에 읽기 및 쓰기 방향이 꺼져 있지만 데이터가 읽히지 않아 데이터 손실이 발생합니다.
쓰기 방향을 닫은 후, 나머지 데이터는 제 시간에 읽지 않아서 비정상적인 연결을 초래합니다.
핀 패킷은 피어에 의해 처리되지 않으므로 타임 아웃 및 단절에 연결됩니다 .
이러한 문제는 특히 TCP 긴 연결 또는 반이중 통신 시나리오에서 발생하기 쉽습니다.
데이터를 보내고 다시 작성하려는 경우 전화하십시오.
stream_socket_shutdown($socket, STREAM_SHUT_WR);
이는 쓰기 방향이 닫혀 있음을 의미하지만 동료가 전송하는 데이터를 기다리며 읽기 방향이 여전히 유지됩니다.
서버와 클라이언트가 먼저 쓰기 방향을 끄야하는 경우 피어가 나머지 데이터를 읽을 시간이 충분해야합니다.
쓰기 방향을 닫은 후에는 연결이 여전히 데이터를 읽을 수 있습니다. 일반적인 접근법은 다음과 같습니다.
// 글쓰기 방향을 닫습니다
stream_socket_shutdown($socket, STREAM_SHUT_WR);
// 계속해서 피어 데이터를 계속 읽으십시오EOF
while (!feof($socket)) {
$data = fread($socket, 8192);
if ($data === false) {
break;
}
// 처리 데이터
}
레거시 데이터를 읽지 않도록하십시오.
먼저 쓰기 방향을 닫고 전송 될 피어 데이터를 알립니다.
피어가 반환 할 수있는 데이터를 읽으십시오.
읽은 후 읽기 방향을 닫거나 전체 연결을 닫으십시오.
Stream_set_timeout을 사용하여 읽기 및 쓰기 시간 초과를 설정하여 연결이 중단되는 차단을 피하십시오.
다음 예제는 서버에 안전한 연결을 작성하는 올바른 방법을 보여줍니다.
$server = stream_socket_server("tcp://0.0.0.0:12345", $errno, $errstr);
if (!$server) {
die("서버를 시작할 수 없습니다: $errstr ($errno)");
}
$client = stream_socket_accept($server);
if ($client) {
// 응답 데이터를 보냅니다
fwrite($client, "Hello from server\n");
// 글쓰기 방향을 닫습니다,클라이언트에게 더 이상 데이터가 없음을 알리십시오
stream_socket_shutdown($client, STREAM_SHUT_WR);
// 클라이언트가 보낸 데이터를 계속 읽으십시오
while (!feof($client)) {
$data = fread($client, 8192);
if ($data === false || $data === "") {
break;
}
echo "클라이언트 데이터를 받았습니다: $data\n";
}
// 연결을 닫으십시오
fclose($client);
}
fclose($server);
커뮤니케이션이 더 이상 수행되지 않는 한 읽기 및 쓰기 방향을 동시에 쓰지 마십시오.
긴 연결을 위해 Stream_Socket_Shutdown에 대한 빈번한 호출을 피하고 하트 비트 패키지와 시간 초과 감지를 합리적으로 사용하십시오.
클라이언트와 서버의 프로토콜 설계가 연결 타이밍 및 순서 폐쇄에 대해 명확하게 확인하십시오.
Blocking을 방지하려면 stream_set_blocking 및 stream_set_timeout을 사용하십시오.
Stream_Socket_Shutdown 은 소켓 연결을 닫는 데 중요한 도구이지만 부적절한 사용은 쉽게 비정상적인 연결 중단으로 이어질 수 있습니다. 폐쇄의 의미를 이해하고, 마감 방향을 합리적으로 선택하고, 마감 후 데이터의 읽기 및 쓰기 순서를 보장하는 것이 문제를 피하고 수정하는 데 핵심입니다. 올바른 시간 초과 설정과 예외 처리를 결합하면 PHP 네트워크 프로그램이보다 안정적이고 신뢰할 수 있습니다.