Sockets 流\u套接字\u服务器:客户端浏览器随机中止?
下面是一个实验性的http服务器应用程序的部分代码,我是从PHP CLI脚本从头开始构建的(为什么?因为我手头有太多的时间)。下面的示例与PHP关于此函数的手册页面更为匹配。我遇到的问题是,当通过浏览器(到目前为止测试的两个独立系统的Firefox或IE8)连接到此服务器应用程序时,浏览器会向服务器发送一个空的请求负载,并且大约每加载6个页面中的1个页面就中止一次 服务器控制台每次都显示“已连接[客户端信息]”。但是,大约六分之一的连接将导致“客户端请求为空”错误。没有给出任何错误,告诉标头/正文对套接字的写入响应失败。浏览器通常会继续阅读我给它的内容,但这是不可用的,因为我无法在不知道它是什么的情况下满足客户端的预期请求 <?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); } ?>Sockets 流\u套接字\u服务器:客户端浏览器随机中止?,sockets,php,Sockets,Php,下面是一个实验性的http服务器应用程序的部分代码,我是从PHP CLI脚本从头开始构建的(为什么?因为我手头有太多的时间)。下面的示例与PHP关于此函数的手册页面更为匹配。我遇到的问题是,当通过浏览器(到目前为止测试的两个独立系统的Firefox或IE8)连接到此服务器应用程序时,浏览器会向服务器发送一个空的请求负载,并且大约每加载6个页面中的1个页面就中止一次 服务器控制台每次都显示“已连接[客户端信息]”。但是,大约六分之一的连接将导致“客户端请求为空”错误。没有给出任何错误,告诉标头/正
我测试了你的代码,似乎用
fread()
读取套接字得到了更好的结果。您还忘记了主循环(while(1)
,while(true)
或(;)
对代码的修改:
- stream\u socket\u accept与@stream\u socket\u accept[有时您会收到警告,因为“连接方没有正确响应”,这当然是
]stream\u socket\u accept()的超时时间。
- 添加了大
循环while(1){}
- 从
to$client\u request=stream\u get\u contents($conn)更改套接字的读取;
while(!preg_match('/\r?\n\r?\n/',$client_request)){$client_request.=fread($conn,1024);}
Addsleep(1)
在stream\u set\u blocking
之后添加sleep(1)
很酷。好多了。出于某种原因,我想stream\u get\u contents()
实际上一直等到收到完整的请求。我猜客户端没有时间发送,在下一次发送时被推了出去($conn=…
来了并重写了连接。它看起来像是(!preg_match…
如果客户端运行缓慢或故意中止,则循环会暂停和阻止其他连接。我应该在此时停止该进程,还是您知道更好的方法?此外,它似乎适用于GET请求,因为标头部分似乎以[line feed][carries return]结尾但是,在POST请求中没有返回可靠的字符模式,POST数据正好低于此值。我一直在想客户端如何告诉我他们的请求消息何时完成。只是发现主,而(1)
循环是不必要的。流\u socket\u accept()
超时可以设置为-1(从不)。这样做可能更好地捕获函数可能抛出的任何其他类型的错误(如果它甚至定义了更多的内部错误案例).总而言之,你让我明白了一个事实,那就是我必须等到客户端完成向我发送完整的请求,而不仅仅是立即处理我收到的任何请求。也许我应该先更深入地阅读http规范,以了解如何处理它们。如果没有其他人响应,我会将此标记为已接受。谢谢!
<?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);
}
}