超简单的 HTTP 套接字服务器,用 PHP 编写,表现出乎意料
Ultra simple HTTP socket server, written in PHP, behaving unexpectedly
tldr;
PHP
中非常小的流套接字服务器
- 行为很奇怪,因为有时它成功地服务于
HTTP
请求,而 有时在同一个进程中失败
- 在不同的浏览器中表现得很奇怪 - 几乎每次都在
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
这让我得到了这些结果:
ERR_CONNECTION_RESET
在 Chrome,几乎每次(可能 20-30 分之一
请求得到预期的响应)
The connection was reset
在 Firefox 中,大约为 2-3 中的 1
请求
- 每次 Internet Explorer 11 中的正确预期响应(是的,
IE 是最好的)。
我做错了什么?是 http headers(我不能说我是否格式不正确)或 socket loop 或..?
您没有读取来自客户端的 HTTP 请求,而是简单地发送您的响应并关闭连接。但是在仍有数据要读取时关闭套接字将导致连接重置发送回客户端,这就是您将在 Chrome 和 ERR_CONNECTION_RESET 中看到的内容。其他浏览器的行为可能不同,如果浏览器可以在处理重置之前显示响应,这也是一个时间问题。
要解决此问题,请先阅读来自客户端的完整请求,然后再关闭套接字。
tldr;
PHP
中非常小的流套接字服务器
- 行为很奇怪,因为有时它成功地服务于
HTTP
请求,而 有时在同一个进程中失败 - 在不同的浏览器中表现得很奇怪 - 几乎每次都在
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
这让我得到了这些结果:
ERR_CONNECTION_RESET
在 Chrome,几乎每次(可能 20-30 分之一 请求得到预期的响应)The connection was reset
在 Firefox 中,大约为 2-3 中的 1 请求- 每次 Internet Explorer 11 中的正确预期响应(是的, IE 是最好的)。
我做错了什么?是 http headers(我不能说我是否格式不正确)或 socket loop 或..?
您没有读取来自客户端的 HTTP 请求,而是简单地发送您的响应并关闭连接。但是在仍有数据要读取时关闭套接字将导致连接重置发送回客户端,这就是您将在 Chrome 和 ERR_CONNECTION_RESET 中看到的内容。其他浏览器的行为可能不同,如果浏览器可以在处理重置之前显示响应,这也是一个时间问题。
要解决此问题,请先阅读来自客户端的完整请求,然后再关闭套接字。