Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1139557
  • 博文数量: 53
  • 博客积分: 10025
  • 博客等级: 上将
  • 技术积分: 1640
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-15 17:05
文章分类

全部博文(53)

文章存档

2011年(1)

2010年(3)

2009年(25)

2008年(24)

我的朋友

分类:

2008-04-29 21:20:56

    继 另类的 Linux在线文本打印和基于 Perl的 Web Service 中,dorainm曾经提到:


:: START QUOTE

    Perl 开始在 $sys{'port'}端口侦听了,如果运行成功的话,然后要开始接收客户请求,下面是实现的关键代码:

sub accept_client(){
    while( $client_socket=accept( CLIENT, SERVER ) ) {
    ( $client_port, $client_ip ) = sockaddr_in( $client_socket );
    $client_ipnum = inet_ntoa( $client_ip );
    $client_host = gethostbyaddr( $client_ip, AF_INET );

    sysread( CLIENT, $client_stream, 4096 );

    printf stdout "Got a Connection From: $client_host [ $client_ipnum ] on Port $client_port\n";
    printf CLIENT "Hello, World\n";
    
    close CLIENT;
    }
}


    这里选用 sysread读取 socket字符流,dorainm尝试了好多方法,比如while( $cllient_stream .= )等,发现都会出现阻塞等情况,唉,暂时用这个吧,等秋后再细细研究!


::END QUOTE

    dorainm用 sysread来读取 socket字符串流

    sysread( CLIENT, $client_stream, 4096 );

    程序在打印发票之类的小字符串时候,倒没有问题,但是打印月报表、季度报表等大量数据的时候,4096终于出现沉不住气了...

    嗯,怎么办!Buffer再大,可能有无法接受的时候; 用while来判断是否结束,1024、1024地一段一段读?
    但是 dorainm也没有系统学过 Perl,到处 google别人的代码来阅读,发现误人子弟的文章真不少,类似 while( sysread(CLIENT,$buff,1024) != 0 )之类的代码,这种判断根本没法解决...

    低调地继续调试着,dorainm想起来,有个HTTP头,里面有规定 Content-Length的长度,有浏览器提交的时候,统计生成的,比如

POST / HTTP/1.1
Host: localhost:port
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 5173

pstr=Hello%2C+World……(&^#&%$^@&#%&^@#$%^&#$)……HELLO


    嗯,终于有个简单的想法了,首先读取,比如1024个字符(保证HTTP读取完毕了,pstr是否读取完毕,暂时不用管),然后用正则,获取HTTP头里面的 Content-Length的值,用统计的
值来重新规划缓冲区,来读取完整的 pstr,这样子就不怕 Buffer不够用了,嘎嘎
   
    好,Action,正则读取 Content-Length的代码如下:

sub get_length()
{
    my $contentlength = $_[0];
    my $null;

    ($null,$contentlength) = split /Content-Length: /, $contentlength;
    ($contentlength,$null) = split /\n/, $contentlength;

    chomp $contentlength;
    return $contentlength;
}


    获取到 Content-Length后,判断,我们之前的缓冲区是否已经足够了,如果不够吶,用 Content-Length这个值当作缓冲区Buffer,来读取完整的 POST值:

    sysread( CLIENT, $a, $conf{'max'} );

    $content_length = &get_length($a);

    if( $content_length > $conf{'max'} )
    {
     $anymore = "";
     sysread( CLIENT, $anymore, $content_length );
     $a .= $anymore;
    }


    嘿嘿,这样子终于解决了~


阅读(6926) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~