Есть ли способ прослушивать новые соединения сокетов во время выполнения цикла do, while в PHP?

#php #asynchronous #websocket #async-await

Вопрос:

Я пытаюсь создать простой тестовый проект PHP, javascript websocket, и я столкнулся с проблемой, из-за которой PHP не будет продолжать цикл while(true), как только я вызову функцию приема сокета. Он ожидает фактического соединения, прежде чем продолжить цикл. Есть ли способ вызвать это асинхронно, чтобы цикл while мог продолжаться? Или есть способ немедленно принять больше входящих подключений после того, как одно из них будет принято? Вот мой код

 <?php
error_reporting(E_ALL);

/* Allow the script to hang around waiting for connections. 
set_time_limit(0);

/* Turn on implicit output flushing so we see what we're getting
as it comes in. 
ob_implicit_flush();*/
$address = 'localhost';
$port = 8080;
$clients = [];
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, $address, $port);
socket_listen($server);
/*$client = acceptConn($server);
$clients[0] = $client;*/

// Send WebSocket handshake headers.

$newclient = socket_accept($server);
handshake($server, $newclient);
$clients[count($clients)] = $newclient;

function handshake($server, $client){
    $request = socket_read($client, 5000);
preg_match('#Sec-WebSocket-Key: (.*)rn#', $request, $matches);
$key = base64_encode(pack(
    'H*',
    sha1($matches[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
));
$headers = "HTTP/1.1 101 Switching Protocolsrn";
$headers .= "Upgrade: websocketrn";
$headers .= "Connection: Upgradern";
$headers .= "Sec-WebSocket-Version: 13rn";
$headers .= "Sec-WebSocket-Accept: $keyrnrn";
socket_write($client, $headers, strlen($headers));
}


// Send messages into WebSocket in a loop.
 do {
    sleep(1);
    //echo "next";
    $content = 'Now: ' . time();
    $response = chr(129) . chr(strlen($content)) . $content;

    


    foreach($clients as $key => $item){
        if(socket_write($item, $response) != 17){
            socket_close($item);
            unset($clients[$key]);
            continue;
            //echo json_encode($clients);
        }
        continue;
    }
    /*echo count($clients);
    $newclient = socket_accept($server);
    echo gettype($newclient);
    $clients[count($clients)] = $client;*/
    
    
    
    
}while (true);


?>
 

Ответ №1:

Я нашел решение. Всем, кому было интересно, что это такое, используйте:

 socket_set_nonblock($socketservervariable);
 

чтобы сервер не ждал подключения клиента, прежде чем продолжить. Однако это создает новую ошибку. При выполнении клиентского рукопожатия socket_read хотел получить сокет, но получил логическое значение false, когда функция socket_accept не обнаружила подключения клиента. Так что это было мое решение этой проблемы:

 $newclient = socket_accept($server);
if($newclient != false){
    handshake($server, $newclient);
    $clients[count($clients)] = $newclient;
    echo "nnNew client connected!nn";
}
 

и это решило все мои проблемы.