错误:PHP脚本中不完整的分块编码


error: incomplete chunked encoding in php scripts

尝试在新的共享服务器帐户上运行一些php脚本,脚本不断挂起并超时,没有错误消息。只有当在Chrome浏览器中运行脚本与web开发人员控制台,我得到了一个提示正在发生的事情:"net::ERR_INCOMPLETE_CHUNKED_ENCODING"是什么,它会说。

Fiddler2更具体一些:

Fiddler.Network。ProtocolViolation - [#165] Transfer-Encoding: Chunked response没有以正确的零大小块结束。

…:

Fiddler.Network。协议违规- [#165][HTTPLint #M012] HTTP块响应体不完整;很可能缺少最终的0大小的块。

我编写了一个测试脚本来演示这个问题。它所做的只是sleep()随机运行20-60秒,然后显示一个随机字符串。默认为10次迭代。

但是这个主机提供商的帮助台一直坚持认为这与php环境中的硬60秒超时有关,我知道这是废话。因此,我编写了第二个测试脚本,该脚本使用Ajax连续多次调用另一个脚本。同样,它非常简单,只是一个sleep(),在40到55秒之间随机运行一段时间,然后生成并显示一个随机的短字符串。

所以它的执行时间不会超过60秒。但它仍然保持失败,尽管在Chrome控制台的xhr调用"net::ERR_EMPTY_RESPONSE"而不是"net::ERR_INCOMPLETE_CHUNKED_ENCODING"。

当我把这个给他们看时,他们实际上承认有问题,这感觉就像一个胜利。但这是短暂的。第二天他们就回来了,说,很抱歉,他们不知道是什么原因造成的,他们无能为力,我考虑过升级到副总裁吗?

我有点痴迷了。我想知道这到底是怎么回事。

我写的第一个测试脚本的代码:
<?php
set_time_limit(3600);
error_reporting(E_ALL); 
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[mt_rand(0, $charactersLength - 1)];
    }
    return $randomString;
}
isset($_REQUEST["limit"]) ? $limit = $_REQUEST["limit"] : $limit = 10;

echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">';
echo "<title>Test Script</title></head><body>";
//ob_start ();
echo "<br><br>A random delay between 20 and 60 seconds will be generated, then a randomly generated string will be displayed<br>The default limit on iterations is ten<br>When the script terminates normally, the phrase '"test complete'" will be output at the bottom<br><br>";
 flush();

for ($i = 0; $i < $limit; $i++) {
  $delay = mt_rand (20, 60);
  echo "<br><br><br>iteration ".($i+1)." - script will now sleep for $delay seconds";
    flush();
  sleep ($delay);
  echo "<br><br>Here is a random string:<br>";
  $length = mt_rand (50, 100);
  echo generateRandomString($length);
    flush();
} 

echo '<br><br>...test complete</body></html>';
ob_end_flush();
?>

你可以去这个页面:http://www.scripttest1.cu.cc/testrongcript.php看看当它在这个服务器上运行时会发生什么。

第二个测试脚本的代码:
<?php
set_time_limit(600);
error_reporting(E_ALL); 
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
isset($_REQUEST["limit"]) ? $limit = $_REQUEST["limit"] : $limit = 15;
isset($_REQUEST["longorshort"]) ? $longorshort = $_REQUEST["longorshort"] : $longorshort = "long";
$start = 1;
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">';
echo "<title>Test Script 2</title></head><body>";
echo '<script src="test_script_js7.js"></script>';
echo "
  <br>Clicking the button below will start the script running
  <br>The script called via XMLHttpRequest will generate a random delay between 40 and 55 seconds (5-10 seconds if '"longorshort'" is set to '"short'" in the url string), then a randomly generated string will be displayed in the table on the bottom
  <br>The default limit on iterations is fifteen
  <br>When the process terminates normally, the phrase '"test complete'" will be output in the '"Main Info'" cell
  <br><b>The script called via XMLHttpRequest will <u>never take more than 60 seconds</u> to complete processing</b>
";
//echo "<img src=http://nzbstar.info/download_batch.png onclick='"getter($limit, '$start', '$longorshort')'"><br>";
echo "<br><img src=start.jpg onclick='"getter_outer($limit, '$start', '$longorshort')'"><br><a href='"javascript:master_switch();'">click here to abort</a>  ";
echo "<table border=1><tr>";
echo "<td valign=top><div id=main_info>Main Info:</div></td>";
echo "<td valign=top><div id=iteration>Iterations:</div></td>";
echo "<td valign=top><div id=message>Messages:</div></td>";
echo "</tr></table>";
echo "<table border=1 style=table-layout:fixed;><tr>";
for ($i = 1; $i <= $limit; $i++) {
  echo "<td valign=top><div class=getter id=post_$i><i>Result $i</i></div></td>";
  if ( ($i%5 == 0) ) {echo "</tr><tr>";}
}
echo "</tr></table>";


echo '</body></html>';
?>

…javascript:

var master_off = false;
var getter_running_now = false;
function getter_outer(limit, i, longorshort){
  if (getter_running_now) {alert ("Script is already running!"); return;}
  getter_running_now = true;
  if (master_off) {document.getElementById("main_info").innerHTML += "<br>master switch off, aborting!"; return;} 
  if (i >= limit) {document.getElementById("main_info").innerHTML += "<br>Got to the next getter when we shouldn't have, there's a bug!"; return;}
  getter(limit, i, longorshort);
}
function getter(limit, i, longorshort){  
  if (master_off) {document.getElementById("main_info").innerHTML += "<br>master switch off, aborting!"; return;} 
  if (i >= limit) {document.getElementById("main_info").innerHTML += "<br>Got to the next getter when we shouldn't have, there's a bug!"; return;}
  var post_number_element = "post_" + i;
  var batch_result_script = "test_script_2a.php?longorshort=" + longorshort;
  document.getElementById("iteration").innerHTML = "Iterations:<br>Doing iteration: " + i;
  document.getElementById(post_number_element).innerHTML = "doing this one...<br>";
  var xmlhttp=new XMLHttpRequest();
  xmlhttp.onreadystatechange=function(){
    if (xmlhttp.readyState==4){
      if (xmlhttp.status==200){
        var result = "<b>result for " + post_number_element + " is:</b><br>" + xmlhttp.responseText + "<br><span style=color:green;>Success!</span>";
        document.getElementById(post_number_element).innerHTML = result;
        i++;
        if (i >= limit) {
          document.getElementById("main_info").innerHTML += "<br><span style=color:green;>Test complete!</span>";
        }
        else {getter(limit, i, longorshort);}
      }
      else {document.getElementById("message").innerHTML += "<br> - <span style=color:red;>http return status for iteration " + i + " was " + xmlhttp.status + "</span>";}
    }
  }
  xmlhttp.open("GET",batch_result_script,true);
  xmlhttp.send();
}

function master_switch(){
  master_off = true;
  document.getElementById("main_info").innerHTML += "<br><span style=color:red;>Master Switch Off!</span>";

}

…以及它通过ajax调用的脚本:

 <?php
set_time_limit(600);
error_reporting(E_ALL); 
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[mt_rand(0, $charactersLength - 1)];
    }
    return $randomString;
}
if ( isset($_REQUEST["longorshort"]) && $_REQUEST["longorshort"] == "short" ) {$delay = mt_rand (5, 10);}
else {$delay = mt_rand (40, 55);}

sleep ($delay);
echo "<br>Here is a random string:<br>";
$length = mt_rand (5, 10);
echo generateRandomString($length);

?>

去这里:http://www.scripttest1.cu.cc/testrongcript_2.php?longorshort=long看看它的作用。与第一个脚本不同,它生成的错误是"空响应"。但我认为这两者是有联系的。

这两个脚本在另一个共享服务器和一个我可以访问的带有LAMP的vps上都可以正常工作。它们还在这个服务器上工作一段时间,然后出现故障。第一个测试脚本在结束之前通常要经过几次迭代。第二个是Ajax,如果"longorshort"被设置为"short",则有时会一直运行到完成。

同样,第一个测试脚本从命令行完美地工作。第二个当然不能在那种环境下正常工作。

服务器在Linux下运行PHP Version 5.4.44和Apache Version 2.4.16。

谷歌一直不是我的朋友。我在Stackoverflow上发帖,正好有5(5)个浏览量,0个回复。

谁能至少给我点提示吗?或者如果做不到这一点,给我指出一个Stackoverflow的替代方案,他们可能会真正回答我的问题?

找到了你的wireshark信息的答案,因为所有的延迟都是这样写的,58秒的延迟让我很困扰。

当Internet Explorer与Web服务器建立持久HTTP连接时(通过使用connection: Keep-Alive头),Internet Explorer重用用于接收初始请求的相同TCP/IP套接字,直到该套接字空闲一分钟。连接空闲一分钟后,ie会重置连接。一个新的TCP/IP套接字用于接收额外的请求。您可能需要更改Internet Explorer中的HTTP KeepAliveTimeout值。

https://support.microsoft.com/en-us/kb/813827

这让我认为其他浏览器必须遵循这个标准,所以你必须在运行脚本时在线发送一些东西来防止关闭连接,因为你不能要求你的客户改变他们的超时值