下面是我从头开始从PHP CLI脚本构建的实验性http服务器应用程序的部分代码(为什么?因为我手上有太多时间)。下面的示例更接近于此函数的PHP手册页。我得到的问题是当通过浏览器连接到这个服务器应用程序(到目前为止测试的两个独立系统中的Firefox或IE8)时,浏览器向服务器发送一个空的请求有效负载,并且大约每6个页面加载中止一次。 / p>
服务器控制台每次都显示“已连接[客户端信息]”。但是,大约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的解决方案,或任何获得更稳定通信的方法?这可以在我的服务器端解决,还是仅仅是典型的浏览器行为?
答案 0 :(得分:1)
我测试了你的代码,看来我用fread()
读取套接字的效果更好。您还忘记了主循环(while(1)
,while(true)
或for(;;)
。
stream_socket_accept()
] while(1) { }
循环$client_request = stream_get_contents($conn);
更改为while( !preg_match('/\r?\n\r?\n/', $client_request) ) { $client_request .= fread($conn, 1024); }
检查下面的源代码(我使用8080端口,因为我已经在80上监听了Apache):
<?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);
}
}
答案 1 :(得分:-1)
在sleep(1)
stream_set_blocking