如果HTTP响应没有Content-Length标头,如何停止从套接字读取?

时间:2009-11-03 22:56:09

标签: perl http sockets

以下代码段读取HTTP响应。假设响应不包含Content-Length标头而Content-Type不是text / html,那么如何终止while循环呢?

(1。不要担心分块传输编码2.没有IO :: Socket)


    while(defined($line = <SOCK>))
    {
        $data .= $line;

        if($line =~ /Content-length:/isg)
        {
            ($cl) = $line =~ /Content-Length: ([0-9]+)/i;
        }

        $line =~ s/\n//g;
        $line =~ s/\r//g;
        if($line eq '' && $cl)
        {
            read(SOCK, $data, $cl, length($data));
            last;
        }
        if($line =~ /<\/html>/) { last; }
    }

3 个答案:

答案 0 :(得分:2)

如果没有Content-Length,并且服务器没有使用分块传输编码,则数据在服务器关闭套接字时结束(您将获得EOF)。有关详细信息,请参阅HTTP规范中的相关部分:http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

代码示例中的真正问题是:

  1. 无法处理仅以'content-length'结尾的标题的情况,如X-Not-Really-Content-Length:
  2. 如果$cl为零或未定义,则永远不要输入读取 (这可能就是您所看到的!)。既然你说没有Content-Length标题就会中断,那么$cl会保持未定义的状态,你永远不会输入你的读取块。
  3. 由于这是perl,您可能需要查看LWP,它处理HTTP处理的许多棘手部分。

答案 1 :(得分:1)

如果您不想再从套接字读取,请不要从套接字读取。如果要关闭套接字,只需将其关闭即可。如果您希望服务器在完成为您的请求提供服务时关闭连接,请确保在您的请求中发送“Connection:close”标头。

如果您认为自己可能会损害服务器的感受,那么您可以阅读剩下的所有内容,而不是对其进行任何操作。但是,这使服务器有机会向您传输无穷无尽的数据,让您的插槽永远保持打开状态。

如果您确实需要在代码中自行处理它,则可能需要单独处理标题和消息正文。看到完整的标题后,您可以检查它是否包含您需要的字段。如果没有,你关闭袜子并返回:

 sub read_sock {
    HEADER: while( <SOCK> ) {
      last if /^[\r\n]+$/; # blank line terminating header

      ... parse header lines into %headers...
      }

    unless( exists $headers{'content-length'} ) {
       warn "No Content-Length! Stopping!\n";
       close SOCK;
       return;
       }

    MESSAGE_BODY: while( <SOCK> ) {
      ... read(), etc ...
      }

    return $message_body;
 }

尽管如此,使用LWP :: UserAgent可能有更好的方法。您可以定义自己的内容处理程序,并在其中执行任何操作。

答案 2 :(得分:0)

如果没有内容长度标题,那么您有三个选项:

  1. 数据中的某种标志,告诉您何时完成
  2. 超时
  3. 等待服务器关闭套接字
  4. 其中没有一个非常强大。