多次接收HTTP数据

时间:2015-08-28 19:34:21

标签: perl sockets

我正在编写一个自定义HTTP服务器来为我自己的JavaScript应用程序提供服务。

使用此代码

,从浏览器中获取标题非常简单
$data_length = 0;
$client_data = "";

while ( <$client_socket> ) {

    if ( /Content-Length: (\d+)/ ) {
        $data_length = $1;
    }

    $client_data .= $_;
    last if ( $_ =~ /^\s*$/ );    # end of headers
}

# Receiving the body-entity (POST data) is where things start getting unpleasant.

$bytes_read  = 0;
$bytes_total = 0;

{
    use bytes;

    $client_data_body = "";
    $bytes_to_read    = $data_length;
    $count_recieve    = 0;

    while ( $bytes_to_read > 0 ) {

        print "Bytes to read: $bytes_to_read\n";

        $client_socket->recv( $client_data_body, $bytes_to_read );
        $bytes_read = length $client_data_body;
        $bytes_total += $bytes_read;
        $bytes_to_read = $bytes_to_read - $bytes_read;
        $client_data .= $client_data_body;

    }

}

在一些迭代之后,上面的代码几乎总是在recv()处挂起。 sysread()的行为方式相同。

这是上述脚本的实际输出

Bytes to read: 48821
Bytes to read: 35168
Bytes to read: 24245
Bytes to read: 7687

此时脚本将永远等待。如果我点击浏览器中的“停止”,我会获得无数Bytes to read: 7687

Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687
Bytes to read: 7687

当然有时这些数字会与这些不同,除了最后一个,它似乎停留在7100和7800之间。

很少,脚本不会挂起,并按照我想要的方式完成它的工作

1 个答案:

答案 0 :(得分:2)

首先,永远不要使用use bytes;。任何使用它本身就是马车。这件好事实际上没有做任何事情。删除它!

至于你无休止的电话recv,这是因为你没有检查EOF或错误。以下是执行您想要的代码:

my $body = '';
while ($bytes_to_read) {
   my $rv = sysread($client_socket, $body, $bytes_to_read, length($body));
   die("Read failed: $!") if !defined($rv);
   die("Read failed: Premature EOF") if !$rv;
   $bytes_to_read -= $rv;
}

我从recv切换到sysread,因为它对像TCP这样的流协议更有意义。

总之,你想要

my $body;
if ($request_method eq 'POST') {
   $body = '';
   if (defined($body_length)) {
      # Content-Length provided.
      my $bytes_to_read = $body_length;
      while ($bytes_to_read) {
         my $rv = sysread($client_socket, $body, $bytes_to_read, length($body));
         die("Read failed: $!") if !defined($rv);
         die("Read failed: Premature EOF") if !$rv;
         $bytes_to_read -= $rv;
      }
   } else {
      # Content-Length not provided.
      while (1) {
         my $rv = sysread($client_socket, $body, 64*1024, length($body));
         die("Read failed: $!") if !defined($rv);
         last if !$rv;
      }
   }
}