继
另类的 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;
}
|
嘿嘿,这样子终于解决了~
阅读(6963) | 评论(0) | 转发(0) |