수색…
TCP 클라이언트 소켓
TCP (전송 제어 프로토콜)를 사용하는 소켓 만들기
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
소켓이 성공적으로 만들어 졌는지 확인하십시오. onSocketFailure
함수는이 항목의 소켓 오류 처리 예제에서 제공됩니다.
if(!is_resource($socket)) onSocketFailure("Failed to create socket");
소켓을 지정된 주소에 연결하십시오.
연결이 실패하면 두 번째 줄은 정상적으로 실패합니다.
socket_connect($socket, "chat.stackoverflow.com", 6667)
or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);
서버에 데이터 보내기
socket_write
함수는 소켓을 통해 바이트를 보낸다. PHP에서 바이트 배열은 일반적으로 인코딩에 영향을받지 않는 문자열로 표현됩니다.
socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");
서버로부터 데이터 수신
다음 스 니펫은 socket_read
함수를 사용하여 서버에서 일부 데이터를 수신합니다.
세 번째 매개 변수로 PHP_NORMAL_READ
를 전달하면 \r
/ \n
바이트까지 PHP_NORMAL_READ
바이트는 반환 값에 포함됩니다.
반대로 PHP_BINARY_READ
전달하면 스트림에서 필요한 양의 데이터를 읽습니다.
이전에 socket_set_nonblock
이 호출되었고 PHP_BINARY_READ
가 사용 된 경우 socket_read
는 즉시 false
를 반환합니다. 그렇지 않으면 메서드는 충분한 데이터 (두 번째 매개 변수의 길이에 도달하거나 줄 끝까지 도달 할 때까지)가 수신되거나 소켓이 닫힐 때까지 차단합니다.
이 예제는 IRC 서버에서 데이터를 읽습니다.
while(true) {
// read a line from the socket
$line = socket_read($socket, 1024, PHP_NORMAL_READ);
if(substr($line, -1) === "\r") {
// read/skip one byte from the socket
// we assume that the next byte in the stream must be a \n.
// this is actually bad in practice; the script is vulnerable to unexpected values
socket_read($socket, 1, PHP_BINARY_READ);
}
$message = parseLine($line);
if($message->type === "QUIT") break;
}
소켓 닫기
소켓을 닫으면 소켓과 관련 자원이 해제됩니다.
socket_close($socket);
TCP 서버 소켓
소켓 생성
TCP를 사용하는 소켓을 만듭니다. 클라이언트 소켓을 만드는 것과 같습니다.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
소켓 바인딩
지정된 포트 (매개 변수 3)에 대해 지정된 네트워크 (매개 변수 2)에서 소켓으로 연결을 바인딩합니다.
두 번째 매개 변수는 일반적으로 모든 네트워크에서 연결을 허용하는 "0.0.0.0"
입니다. 그것은 또한 할 수있다.
socket_bind
의 오류의 한 가지 일반적인 원인은 지정된 주소가 이미 다른 프로세스에 바인드되어 있다는 것 입니다. 소켓이 해제 될 수 있도록 다른 프로세스가 보통 죽습니다 (대개 실수로 중요한 프로세스가 죽는 것을 방지하기 위해 수동으로).
socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");
청취하도록 소켓 설정
socket_listen
사용하여 들어오는 연결을 수신 대기하도록 socket_listen
. 두 번째 매개 변수는 허용되기 전에 큐잉을 허용하는 최대 연결 수입니다.
socket_listen($socket, 5);
연결 처리 중
TCP 서버는 실제로 자식 연결을 처리하는 서버입니다. socket_accept
는 새 하위 연결을 만듭니다.
$conn = socket_accept($socket);
socket_accept
에서 연결을위한 데이터 전송은 TCP 클라이언트 소켓의 데이터 전송과 동일 합니다 .
이 연결을 닫아야하는 경우 socket_close($conn);
호출하십시오 socket_close($conn);
직접. 원본 TCP 서버 소켓에는 영향을 미치지 않습니다.
서버 닫기
반면에, socket_close($socket);
서버가 더 이상 사용되지 않으면 호출되어야합니다. 이렇게하면 다른 프로세스가 주소에 바인드 할 수 있도록 TCP 주소도 해제됩니다.
소켓 오류 처리
socket_last_error
는 소켓 확장에서 마지막 오류의 오류 ID를 가져 오는 데 사용할 수 있습니다.
socket_strerror
는 ID를 사람이 읽을 수있는 문자열로 변환하는 데 사용할 수 있습니다.
function onSocketFailure(string $message, $socket = null) {
if(is_resource($socket)) {
$message .= ": " . socket_strerror(socket_last_error($socket));
}
die($message);
}
UDP 서버 소켓
UDP (사용자 데이터 그램 프로토콜) 서버는 TCP와 달리 스트림 기반이 아닙니다. 그것은 패킷 기반입니다. 즉, 클라이언트는 "패킷"이라는 단위로 서버에 데이터를 보내고 클라이언트는 클라이언트의 주소로 클라이언트를 식별합니다. 동일한 클라이언트에서 보낸 다른 패킷을 관련시키는 내장 함수가 없습니다 (동일한 클라이언트의 데이터가 socket_accept
의해 생성 된 특정 리소스로 처리되는 TCP와는 다릅니다). UDP 패킷이 도착할 때마다 새로운 TCP 연결이 수락되고 닫히는 것으로 생각할 수 있습니다.
UDP 서버 소켓 만들기
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
소켓에 주소 바인딩하기
매개 변수는 TCP 서버의 매개 변수와 동일합니다.
socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);
패킷 보내기
이 줄은 UDP 패킷의 $data
를 $address
: $port
보냅니다.
socket_sendto($socket, $data, strlen($data), 0, $address, $port);
패킷 수신
다음 스 니펫은 클라이언트 인덱스 방식으로 UDP 패킷을 관리하려고 시도합니다.
$clients = [];
while (true){
socket_recvfrom($socket, $buffer, 32768, 0, $ip, $port) === true
or onSocketFailure("Failed to receive packet", $socket);
$address = "$ip:$port";
if (!isset($clients[$address])) $clients[$address] = new Client();
$clients[$address]->handlePacket($buffer);
}
서버 닫기
socket_close
는 UDP 서버 소켓 리소스에서 사용할 수 있습니다. 이렇게하면 다른 프로세스가이 주소에 바인딩 할 수 있도록 UDP 주소가 해제됩니다.