PHP
Sockets
Zoeken…
TCP-client socket
Een socket maken die het TCP (Transmission Control Protocol) gebruikt
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Zorg ervoor dat de socket met succes is gemaakt. De functie onSocketFailure
komt uit het voorbeeld van socketfouten in dit onderwerp.
if(!is_resource($socket)) onSocketFailure("Failed to create socket");
Verbind de aansluiting met een gespecificeerd adres
De tweede regel mislukt netjes als de verbinding is mislukt.
socket_connect($socket, "chat.stackoverflow.com", 6667)
or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);
Gegevens naar de server verzenden
De functie socket_write
verzendt bytes door een socket. In PHP wordt een bytearray voorgesteld door een string, die normaal niet coderingsongevoelig is.
socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");
Gegevens ontvangen van de server
Het volgende fragment ontvangt enkele gegevens van de server met behulp van de socket_read
functie.
Doorgeven van PHP_NORMAL_READ
als de derde parameter leest tot een \r
/ \n
byte, en deze byte is opgenomen in de retourwaarde.
Als u PHP_BINARY_READ
, wordt daarentegen de vereiste hoeveelheid gegevens uit de stream gelezen.
Als socket_set_nonblock
werd aangeroepen en PHP_BINARY_READ
wordt gebruikt, zal socket_read
onmiddellijk false
retourneren. Anders blokkeert de methode totdat er voldoende gegevens zijn ontvangen (om de lengte in de tweede parameter te bereiken of om een einde van de lijn te bereiken) of de socket wordt gesloten.
Dit voorbeeld leest gegevens van een zogenaamd 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;
}
Contactdoos sluiten
Het sluiten van de socket maakt de socket en de bijbehorende bronnen vrij.
socket_close($socket);
TCP-serveraansluiting
Socket creatie
Maak een socket die TCP gebruikt. Het is hetzelfde als het maken van een client-socket.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Socket binding
Verbind verbindingen van een bepaald netwerk (parameter 2) voor een specifieke poort (parameter 3) met de socket.
De tweede parameter is meestal "0.0.0.0"
, die verbinding van alle netwerken accepteert. Het kan ook
Een veel voorkomende oorzaak van fouten van socket_bind
is dat het opgegeven adres al aan een ander proces is gebonden . Andere processen worden meestal gedood (meestal handmatig om te voorkomen dat per ongeluk kritieke processen worden gedood) zodat de sockets worden vrijgemaakt.
socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");
Zet een aansluiting op luisteren
Laat de socket naar binnenkomende verbindingen luisteren met socket_listen
. De tweede parameter is het maximale aantal verbindingen dat wachtrijen mogelijk maakt voordat ze worden geaccepteerd.
socket_listen($socket, 5);
Behandeling verbinding
Een TCP-server is eigenlijk een server die onderliggende verbindingen verwerkt. socket_accept
maakt een nieuwe onderliggende verbinding.
$conn = socket_accept($socket);
Gegevensoverdracht voor een verbinding van socket_accept
is hetzelfde als die voor een TCP-clientsocket .
Wanneer deze verbinding moet worden gesloten, roept u socket_close($conn);
direct. Dit heeft geen invloed op de oorspronkelijke TCP-server-socket.
Server wordt gesloten
Aan de andere kant, socket_close($socket);
moet worden aangeroepen wanneer de server niet meer wordt gebruikt. Hiermee wordt ook het TCP-adres vrijgegeven, waardoor andere processen kunnen binden aan het adres.
Omgaan met socketfouten
socket_last_error
kan worden gebruikt om de fout-ID van de laatste fout van de sockets-extensie te krijgen.
socket_strerror
kan worden gebruikt om de ID om te zetten in voor mensen leesbare tekenreeksen.
function onSocketFailure(string $message, $socket = null) {
if(is_resource($socket)) {
$message .= ": " . socket_strerror(socket_last_error($socket));
}
die($message);
}
UDP-serveraansluiting
Een UDP-server (user datagram protocol) is, in tegenstelling tot TCP, niet streamgebaseerd. Het is op pakketten gebaseerd, dat wil zeggen een client verzendt gegevens in eenheden die "pakketten" worden genoemd naar de server en de client identificeert clients aan de hand van hun adres. Er is geen ingebouwde functie die betrekking heeft op verschillende pakketten die vanaf dezelfde client worden verzonden (in tegenstelling tot TCP, waarbij gegevens van dezelfde client worden verwerkt door een specifieke bron die is gemaakt door socket_accept
). Het kan worden gedacht als een nieuwe TCP-verbinding wordt geaccepteerd en gesloten telkens wanneer een UDP-pakket arriveert.
Een UDP-server socket maken
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
Een socket aan een adres binden
De parameters zijn dezelfde als die voor een TCP-server.
socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);
Een pakket versturen
Deze regel verzendt $data
in een UDP-pakket naar $address
: $port
.
socket_sendto($socket, $data, strlen($data), 0, $address, $port);
Een pakket ontvangen
Het volgende fragment probeert UDP-pakketten op een client-geïndexeerde manier te beheren.
$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);
}
Server wordt gesloten
socket_close
kan worden gebruikt op de socket_close
van de UDP-server. Hiermee wordt het UDP-adres vrijgemaakt, waardoor andere processen kunnen binden aan dit adres.