stream_socket_server: клиентский браузер случайно прерывается? - PullRequest
0 голосов
/ 16 июля 2010

Ниже приведен частичный код экспериментального приложения http-сервера, который я создаю с нуля из сценария PHP CLI (почему? Потому что у меня слишком много времени в моих руках).Пример ниже более точно соответствует странице руководства PHP по этой функции.Проблема, которую я получаю, заключается в том, что при подключении к этому серверному приложению через браузер (Firefox или IE8 из двух отдельных систем, протестированных до сих пор), браузер отправляет на сервер пустую полезную нагрузку и прерывает примерно каждую загрузку страницы 1 на 6.1001 *

Консоль сервера каждый раз отображает сообщение «Connected with [client info]».Однако примерно 1 из 6 подключений приведет к ошибке «Клиентский запрос пуст».Не сообщается об ошибке, сообщающей заголовку / телу ответ ошибка записи в сокет.Браузер, как правило, продолжает читать то, что я ему даю, но это бесполезно, поскольку я не могу выполнить намеченный запрос клиента, не зная, что это такое.

<?php

$s_socket_uri = 'tcp://localhost:80';
// establish the server on the above socket
$s_socket = stream_socket_server($s_socket_uri, $errno, $errstr, 30) OR
    trigger_error("Failed to create socket: $s_socket_uri, Err($errno) $errstr", E_USER_ERROR);
$s_name = stream_socket_get_name($s_socket, false) OR
    trigger_error("Server established, yet has no name.  Fail!", E_USER_ERROR);
if (!$s_socket || !$s_name) {return false;}

/*
   Wait for connections, handle one client request at a time
   Though to not clog up the tubes, maybe a process fork is
   needed to handle each connection?
*/
while($conn = stream_socket_accept($s_socket, 60, $peer)) {
    stream_set_blocking($conn, 0);

    // Get the client's request headers, and all POSTed values if any
    echo "Connected with $peer.  Request info...\n";
    $client_request = stream_get_contents($conn);
    if (!$client_request) {
        trigger_error("Client request is empty!");
        }
    echo $client_request."\n\n";  // just for debugging

    /*
      <Insert request handling and logging code here>
    */

    // Build headers to send to client
    $send_headers = "HTTP/1.0 200 OK\n"
        ."Server: mine\n"
        ."Content-Type: text/html\n"
        ."\n";

    // Build the page for client view
    $send_body = "<h1>hello world</h1>";

    // Make sure the communication is still active
    if ((int) fwrite($conn, $send_headers . $send_body) < 1) {
        trigger_error("Write to socket failed!");
        }

    // Response headers and body sent, time to end this connection
    stream_socket_shutdown($conn, STREAM_SHUT_WR);
    }

?>

Есть ли какое-либо решение, позволяющее снизить количество непреднамеренных прерываний до 0, или какой-либо способ повысить стабильность связи?Это разрешимо со стороны моего сервера или просто типичное поведение браузера?

Ответы [ 2 ]

1 голос
/ 16 июля 2010

Я проверил ваш код и, кажется, получил лучшие результаты при чтении сокета с fread().Вы также забыли основной цикл (while(1), while(true) или for(;;).

Изменения в вашем коде:

  • stream_socket_accept с @ stream_socket_accept [иногда вы получаете предупреждения, потому что " подключенная сторона не ответила должным образом ", что, конечно, является тайм-аутом stream_socket_accept()]
  • Добавлен большой while(1) { } loop
  • Изменено чтение из сокета с $client_request = stream_get_contents($conn); на while( !preg_match('/\r?\n\r?\n/', $client_request) ) { $client_request .= fread($conn, 1024); }

Проверьте приведенный ниже исходный код (я использовал порт 8080, потому что у меня уже было прослушивание Apache80):

<?php

$s_socket_uri = 'tcp://localhost:8080';
$s_socket = stream_socket_server($s_socket_uri, $errno, $errstr, 30) OR
    trigger_error("Failed to create socket: $s_socket_uri, Err($errno) $errstr", E_USER_ERROR);
$s_name = stream_socket_get_name($s_socket, false) OR
    trigger_error("Server established, yet has no name.  Fail!", E_USER_ERROR);
if (!$s_socket || !$s_name) {return false;}

while(1)
{
    while($conn = @stream_socket_accept($s_socket, 60, $peer)) 
    {
        stream_set_blocking($conn, 0);
        echo "Connected with $peer.  Request info...\n";
        //    $client_request = stream_get_contents($conn);

        $client_request = "";
        // Read until double \r
        while( !preg_match('/\r?\n\r?\n/', $client_request) )
        {
            $client_request .= fread($conn, 1024);
        }

        if (!$client_request) 
        {
            trigger_error("Client request is empty!");
        }
        echo $client_request."\n\n";
        $headers = "HTTP/1.0 200 OK\n"
            ."Server: mine\n"
            ."Content-Type: text/html\n"
            ."\n";
        $body = "<h1>hello world</h1><br><br>".$client_request;
        if ((int) fwrite($conn, $headers . $body) < 1) {
            trigger_error("Write to socket failed!");
            }
    stream_socket_shutdown($conn, STREAM_SHUT_WR);
    }
}
0 голосов
/ 29 октября 2014

Добавить sleep(1) после stream_set_blocking

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...