Szukaj…


Gniazdo klienta TCP

Tworzenie gniazda korzystającego z protokołu TCP (Transmission Control Protocol)

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

Upewnij się, że gniazdo zostało pomyślnie utworzone. Funkcja onSocketFailure pochodzi z przykładu Obsługa błędów gniazda w tym temacie.

if(!is_resource($socket)) onSocketFailure("Failed to create socket");

Podłącz gniazdo do określonego adresu

Druga linia kończy się niepowodzeniem w przypadku awarii połączenia.

socket_connect($socket, "chat.stackoverflow.com", 6667)
        or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);

Wysyłanie danych na serwer

Funkcja socket_write wysyła bajty przez gniazdo. W PHP tablica bajtów jest reprezentowana przez ciąg znaków, który zwykle nie jest wrażliwy na kodowanie.

socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");

Odbieranie danych z serwera

Poniższy fragment socket_read odbiera niektóre dane z serwera za pomocą funkcji socket_read .

Przekazanie PHP_NORMAL_READ jako trzeciego parametru odczytuje aż do bajtu \r / \n , a ten bajt jest zawarty w wartości zwracanej.

PHP_BINARY_READ , PHP_BINARY_READ odczytuje wymaganą ilość danych ze strumienia.

Jeśli socket_set_nonblock został wezwany przed i PHP_BINARY_READ służy, socket_read zwróci false natychmiast. W przeciwnym razie metoda blokuje się do momentu odebrania wystarczającej ilości danych (aby osiągnąć długość drugiego parametru lub osiągnąć koniec linii) lub gniazdo zostanie zamknięte.

Ten przykład czyta dane z rzekomo serwera 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;
}

Zamykanie gniazda

Zamknięcie gniazda zwalnia gniazdo i związane z nim zasoby.

socket_close($socket);

Gniazdo serwera TCP

Tworzenie gniazda

Utwórz gniazdo korzystające z protokołu TCP. To samo co tworzenie gniazda klienta.

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

Oprawa gniazdowa

Powiąż połączenia z danej sieci (parametr 2) dla określonego portu (parametr 3) z gniazdem.

Drugi parametr to zazwyczaj "0.0.0.0" , który akceptuje połączenie ze wszystkich sieci. Może też

Jedną z częstych przyczyn błędów z socket_bind jest to, że podany adres jest już powiązany z innym procesem . Inne procesy są zwykle zabijane (zwykle ręcznie, aby zapobiec przypadkowemu zabiciu procesów krytycznych), aby uwolnić gniazda.

socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");

Ustaw gniazdo do słuchania

Spraw, aby gniazdo nasłuchiwało połączeń przychodzących za pomocą socket_listen . Drugi parametr to maksymalna liczba połączeń, które umożliwiają kolejkowanie przed ich zaakceptowaniem.

socket_listen($socket, 5);

Obsługa połączenia

Serwer TCP to tak naprawdę serwer, który obsługuje połączenia podrzędne. socket_accept tworzy nowe połączenie potomne.

$conn = socket_accept($socket);

Przesyłanie danych dla połączenia z socket_accept jest takie samo jak dla gniazda klienta TCP .

Kiedy to połączenie powinno zostać zamknięte, wywołaj socket_close($conn); bezpośrednio. Nie wpłynie to na oryginalne gniazdo serwera TCP.

Zamykanie serwera

Z drugiej strony socket_close($socket); należy wywoływać, gdy serwer nie jest już używany. Spowoduje to również zwolnienie adresu TCP, umożliwiając innym procesom powiązanie z tym adresem.

Obsługa błędów gniazd

socket_last_error może być użyty do uzyskania identyfikatora błędu ostatniego błędu z rozszerzenia gniazd.

socket_strerror może być użyty do konwersji identyfikatora na ciągi czytelne dla człowieka.

function onSocketFailure(string $message, $socket = null) {
    if(is_resource($socket)) {
        $message .= ": " . socket_strerror(socket_last_error($socket));
    }
    die($message);
}

Gniazdo serwera UDP

Serwer UDP (protokół datagramu użytkownika), w przeciwieństwie do TCP, nie jest oparty na strumieniu. Opiera się na pakietach, tzn. Klient wysyła dane w jednostkach zwanych „pakietami” do serwera, a klient identyfikuje klientów na podstawie ich adresu. Nie ma wbudowanej funkcji, która dotyczy różnych pakietów wysyłanych z tego samego klienta (w przeciwieństwie do TCP, gdzie dane z tego samego klienta są obsługiwane przez określony zasób utworzony przez socket_accept ). Można to uznać za nowe połączenie TCP akceptowane i zamykane za każdym razem, gdy przybywa pakiet UDP.

Tworzenie gniazda serwera UDP

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

Powiązanie gniazda z adresem

Parametry są takie same jak dla serwera TCP.

socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);

Wysyłanie pakietu

Ta linia wysyła $data w pakiecie UDP na $address : $port .

socket_sendto($socket, $data, strlen($data), 0, $address, $port);

Odbieranie pakietu

Poniższy fragment próbuje zarządzać pakietami UDP w sposób indeksowany przez klienta.

$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);
}

Zamykanie serwera

socket_close może być używany w zasobie gniazda serwera UDP. Spowoduje to zwolnienie adresu UDP, umożliwiając innym procesom powiązanie z tym adresem.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow