超简单的 HTTP 套接字服务器,用 PHP 编写,表现出乎意料

Ultra simple HTTP socket server, written in PHP, behaving unexpectedly

tldr;

  1. PHP
  2. 中非常小的流套接字服务器
  3. 行为很奇怪,因为有时它成功地服务于 HTTP 请求,而 有时在同一个进程中失败
  4. 在不同的浏览器中表现得很奇怪 - 几乎每次都在 Chrome 中失败,而在 IE11[ 中从来没有=42=]

代码:

$server = stream_socket_server("tcp://0.0.0.0:4444", $errno, $errorMessage);

if ($server === false) 
    throw new UnexpectedValueException("Could not bind to socket: $errorMessage");

$e = "\r\n";
$headers = array(
    "HTTP/1.1 200 OK",
    "Date: " . date('D') . ', ' . date('m') . ' '  . date('M') . ' ' . date('Y') . ' ' . date('H:i:s') . ' GMT' ,
    'Server: MySpeedy',
    'Connection: close',
    'Content-Type: text/plain',
    'Content-Length: 2'
);

$headers = implode($e, $headers) . $e .  $e .'ok';

for (;;) 
{
    $client = stream_socket_accept($server);

    if ($client) 
    {
        echo 'Connection accepted from '.stream_socket_get_name($client, false) . $e;

        fwrite($client, $headers);
        fclose($client);
    }
}

给我这个 http 响应(telnet 结果):

HTTP/1.1 200 OK
Date: Fri, 11 Nov 2015 20:09:02 GMT
Server: MySpeedy
Connection: close
Content-Type: text/plain
Content-Length: 2

ok

这让我得到了这些结果:

我做错了什么?是 http headers(我不能说我是否格式不正确)或 socket loop 或..?

您没有读取来自客户端的 HTTP 请求,而是简单地发送您的响应并关闭连接。但是在仍有数据要读取时关闭套接字将导致连接重置发送回客户端,这就是您将在 Chrome 和 ERR_CONNECTION_RESET 中看到的内容。其他浏览器的行为可能不同,如果浏览器可以在处理重置之前显示响应,这也是一个时间问题。

要解决此问题,请先阅读来自客户端的完整请求,然后再关闭套接字。