🌊

【PHP】HTTP/1 サーバーに socket_select を使う

2024/07/22に公開
<?php
// https://gist.github.com/nmmmnu/1408434
// https://www.php.net/manual/en/function.socket-select.php#56241

$address = '0.0.0.0';
$port    = 8000;
$max = 10;
$clients = [];

$sock = socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
socket_set_nonblock($sock);

socket_bind($sock, $address, $port);
socket_listen($sock, $max);

printf("serving http://localhost:%s\n", $port);

$read = [$sock];

while (true) {
    $ready = socket_select($read, $write, $except, 10);

    if ($ready == 0){
        continue;
    }

    if (in_array($sock, $read)) {
        $clients[] = socket_accept($sock);
        $key = array_search($sock, $read);
        unset($read[$key]);
   }

    foreach($read as $client) {
        $input = socket_read($client, 1024);

        if (empty($input)) {
            $key = array_search($client, $clients);
            unset($clients[$key]);
            continue;
        }

        $msg = "HTTP/1.1 200 OK\r\n".
               "Content-Type: text/html; charset=UTF-8\r\n".
               "Content-Length: 12\r\n".
               "Connection: Close\r\n".
               "\r\n".
               "Hello World\n";
        socket_write($client, $msg);
    }

}

socket_close($sock);

curl でのリクエストは次のとおり

curl -v --http1.1 http://localhost:8000

Discussion