PHP
Sockets
Sök…
TCP-klientuttag
Skapa ett uttag som använder TCP (Transmission Control Protocol)
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Se till att uttaget har skapats. onSocketFailure
funktionen kommer från Exempel på hantering av socketfel i detta ämne.
if(!is_resource($socket)) onSocketFailure("Failed to create socket");
Anslut uttaget till en angiven adress
Den andra raden misslyckas graciöst om anslutningen misslyckades.
socket_connect($socket, "chat.stackoverflow.com", 6667)
or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);
Skickar data till servern
Funktionen socket_write
skickar byte genom ett socket. I PHP representeras en byte-array av en sträng, som normalt är kodande-okänslig.
socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");
Ta emot data från servern
Följande kodavsnitt tar emot en del data från servern med socket_read
funktionen.
Att passera PHP_NORMAL_READ
som den tredje parametern läser tills en \r
/ \n
byte, och denna byte ingår i returvärdet.
Genom att passera PHP_BINARY_READ
tvärtom den mängd data som krävs från strömmen.
Om socket_set_nonblock
anropades tidigare och PHP_BINARY_READ
används kommer socket_read
att returnera false
omedelbart. I annat fall blockeras metoden tills tillräckligt med data (för att nå längden i den andra parametern, eller för att nå en linje som slutar) har tagits emot, eller socket är stängt.
Det här exemplet läser data från en förment IRC-server.
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;
}
Stäng uttaget
Att stänga uttaget frigör uttaget och dess tillhörande resurser.
socket_close($socket);
TCP-serveruttag
Socket skapande
Skapa ett uttag som använder TCP. Det är samma sak som att skapa ett klientuttag.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Uttagsbindning
Bind anslutningar från ett givet nätverk (parameter 2) för en specifik port (parameter 3) till uttaget.
Den andra parametern är vanligtvis "0.0.0.0"
, som accepterar anslutning från alla nätverk. Det kan också
En vanlig orsak till fel från socket_bind
är att den angivna adressen redan är bunden till en annan process . Andra processer dödas vanligtvis (vanligtvis manuellt för att förhindra att kritiska processer dödas av misstag) så att uttagen skulle frigöras.
socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");
Ställ in ett uttag för att lyssna
Låt uttaget lyssna på inkommande anslutningar med socket_listen
. Den andra parametern är det maximala antalet anslutningar som tillåter kö innan de accepteras.
socket_listen($socket, 5);
Hantering av anslutning
En TCP-server är faktiskt en server som hanterar barnanslutningar. socket_accept
skapar en ny socket_accept
.
$conn = socket_accept($socket);
Dataöverföring för en anslutning från socket_accept
är densamma som för en TCP-klientuttag .
När denna anslutning ska stängas, ring socket_close($conn);
direkt. Detta påverkar inte det ursprungliga TCP-serveruttaget.
Stänger servern
Å andra sidan socket_close($socket);
bör ringas när servern inte längre används. Detta kommer också att frigöra TCP-adressen, vilket gör att andra processer kan binda till adressen.
Hantering av sockelfel
socket_last_error
kan användas för att få fel-ID för det sista felet från sockelförlängningen.
socket_strerror
kan användas för att konvertera ID till mänskliga läsbara strängar.
function onSocketFailure(string $message, $socket = null) {
if(is_resource($socket)) {
$message .= ": " . socket_strerror(socket_last_error($socket));
}
die($message);
}
UDP-serveruttag
En UDP-server (användardatagramprotokoll) är, till skillnad från TCP, inte strömbaserad. Det är paketbaserat, dvs. en klient skickar data i enheter som kallas "paket" till servern, och klienten identifierar klienter med deras adress. Det finns ingen inbyggd funktion som relaterar olika paket som skickas från samma klient (till skillnad från TCP, där data från samma klient hanteras av en specifik resurs skapad av socket_accept
). Det kan tänkas som en ny TCP-anslutning accepteras och stängs varje gång ett UDP-paket anländer.
Skapa ett UDP-serveruttag
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
Binda ett uttag till en adress
Parametrarna är desamma som för en TCP-server.
socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);
Skickar ett paket
Denna rad skickar $data
i ett UDP-paket till $address
: $port
.
socket_sendto($socket, $data, strlen($data), 0, $address, $port);
Ta emot ett paket
Följande fragment försöker hantera UDP-paket på ett klientindexerat sätt.
$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);
}
Stänger servern
socket_close
kan användas på UDP-serverns socket-resurs. Detta kommer att befria UDP-adressen, vilket gör att andra processer kan binda till denna adress.