lwknet
06-24-2004, 04:23 AM
below is my perl code, it runs in the background, a script to stay alive forever, it uses IO::Socket, listen to port 7890 on localhost, and create another IO object to pipe output to the port num supplied by the incoming request, i'm gonna run this script as a web services for geoip lookup
i've tested it on both linux redhat 9 and windows 2000 command prompt, both have memory leak just after the ~1600th request, in ~10kb incremental memory usage per request, say it stays steady on ~16MB memory usage before the ~1600th, but this num jumps to ~20MB on the ~2000th
i just don't know why???
any experts out there???
#!/usr/bin/perl -w
##### module usage
use strict;
use Benchmark;
use IO::Socket;
##### declare
our(%token,%cnt,%geo,%cgi,$object,@IP,@MONTHLONG,@MONTHSHORT,@WEEKLONG,@WEEKSHORT);
my(%sub,%tmp,$tmp,@TMP);
##### var
$cgi{db}='/home/lwkstudi/host.lwkstudio.com/db';
##### IO socket, bind & listen
$cgi{object}=new IO::Socket::INET(
LocalHost=>'localhost',
LocalPort=>7890,
Proto=>'tcp',
Listen=>10000,
Reuse=>1);
$cgi{object} or die "no socket :$!";
##### init loading
LoadDB();
LoadToken();
LoadTime();
open(LOG,">>$cgi{db}/geobyip.log");
flock(LOG,2);
##### init success
print "listening on clients\n";
##### accept
while(($object,$cgi{in_ip})=$cgi{object}->accept()){
$cgi{in_sock}=<$object>;
chomp($cgi{in_sock});
L1: for(1){
if($cgi{in_sock}=~/^LoadDB$/i){
LoadDB();
PrintLog("[signal] $cgi{in_sock}");
last L1;
}elsif($cgi{in_sock}=~/^LoadToken$/i){
LoadToken();
PrintLog("[signal] $cgi{in_sock}");
last L1;
}elsif($cgi{in_sock}=~/^(quit|do)$/i){
last L1;
}elsif($cgi{in_sock}=~/^(stop|kill|exit|PrintToken)$/i){
PrintToken();
PrintLog("[signal] $cgi{in_sock}");
GoExit() if($cgi{in_sock}=~/^(kill|exit|stop)$/i);
last L1;
}else{
$cnt{bm_start}=new Benchmark;
$cnt{$_}='' foreach('Token','Port','ErrorMsg','IP','IP10','CountryCode','Country','Time','Benchmark');
($cnt{Year},$cnt{Month},$cnt{Day},$cnt{Hour},$cnt{Minute},$cnt{Second})=split(/\:/,GetTime('YYYY:MM:DD:hh:mm:ss',-3600*8));
$cnt{(split(/\:/))[0]}=(split(/\:/))[1] foreach(split(/\s+/,$cgi{in_sock}));
if($token{$cnt{Token}.'.m'} && $token{$cnt{Token}.'.u'}){
if($token{$cnt{Token}.'.m'}>$token{$cnt{Token}.'.u'}){
$token{$cnt{Token}.'.u'}++;
$cnt{IP10}=$1*16777216+$2*65536+$3*256+$4 if($cnt{IP}=~/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/);
if($cnt{IP10}=~/^[0-9]{8,10}$/){
$cnt{IP10}="0$cnt{IP10}" while(length($cnt{IP10})<10);
$tmp{up}=$cgi{scalarIP};
$tmp{down}=0;
$tmp{last}=0;
while(1){
$tmp{this}=$tmp{up}+$tmp{down};
$tmp{this}=(split(/\./,$tmp{this}/2))[0];
last if($tmp{this} eq $tmp{last});
$tmp{last}=$tmp{this};
($tmp{1},$tmp{2},$tmp{3})=(split(/\,/,$IP[$tmp{this}]))[0,1,2];
if($cnt{IP10}<$tmp{1}){
$tmp{up}=$tmp{this};
}elsif($cnt{IP10}>$tmp{2}){
$tmp{down}=$tmp{this};
}elsif($cnt{IP10}>=$tmp{1} && $cnt{IP10}<=$tmp{2}){
$cnt{CountryCode}=$tmp{3};
chomp($cnt{CountryCode});
last;
}
}
if($cnt{CountryCode}){
$cnt{Country}=$geo{$cnt{CountryCode}};
}else{
$cnt{ErrorMsg}='not found';
}
}else{
$cnt{ErrorMsg}='invalid ip';
}
}else{
$cnt{ErrorMsg}='token quota exceeded';
}
}else{
$cnt{ErrorMsg}='invalid token';
}
$cnt{Benchmark}=$1 if(timestr(timediff(new Benchmark,$cnt{bm_start}))=~/\=\s+([0-9\.]+)\s+CPU\)$/);
PrintLog("[access] $cnt{Token} $cnt{IP} $cnt{Port}");
Output();
undef(%cnt);
}
}
}
##### sub PrintLog
sub PrintLog {
print LOG "$MONTHSHORT[$cnt{Month}] $cnt{Day} $cnt{Hour}:$cnt{Minute}:$cnt{Second} $cnt{Year} $_[0]\n";
}
##### sub Ouput
sub Output {
if($cgi{out_sock}=new IO::Socket::INET(PeerAddr=>'localhost',PeerPort=>$cnt{Port},Proto=>'tcp')){
print {$cgi{out_sock}} <<HTML;
<?xml version="1.0" encoding="UTF-8" ?>
<LwkStudio>
<Server>
<ServerName>xml.geobyip.com</ServerName>
<Token>$cnt{Token}</Token>
<ErrorMsg>$cnt{ErrorMsg}</ErrorMsg>
<Time>$cnt{Time}</Time>
<Benchmark>$cnt{Benchmark} sec</Benchmark>
</Server>
<Request>
<IP>$cnt{IP}</IP>
<IP10>$cnt{IP10}</IP10>
</Request>
<Response>
<CountryCode>$cnt{CountryCode}</CountryCode>
<Country>$cnt{Country}</Country>
</Response>
</LwkStudio>
HTML
close($cgi{out_sock});
}
}
##### sub LoadDB
sub LoadDB {
(@IP,%geo)=undef;
open(A,"$cgi{db}/ip.db");
@IP=<A>;
$cgi{scalarIP}=scalar(@IP);
close(A);
open(A,"$cgi{db}/geo.db");
while(defined($cgi{line}=<A>)){
chomp($cgi{line});
($tmp{1},$tmp{2})=(split(/\,/,$cgi{line}))[0,1];
$geo{$tmp{1}}=$tmp{2};
}
close(A);
}
##### sub LoadToken
sub LoadToken {
undef(%token);
open(A,"$cgi{db}/token.db");
while(defined($cgi{line}=<A>)){
chomp($cgi{line});
($tmp{1},$tmp{2},$tmp{3})=(split(/\,/,$cgi{line}))[0,1,2];
$token{$tmp{1}.'.m'}=$tmp{2};
$token{$tmp{1}.'.u'}=$tmp{3};
}
close(A);
}
##### sub PrintToken
sub PrintToken {
open(A,">$cgi{db}/token.db");
foreach(sort(keys(%token))){
($tmp{1},$tmp{2},$tmp{3},$tmp{4},$tmp{5})=(split(/\./))[0,1,2,3,4];
$tmp{IP}=join('.',($tmp{1},$tmp{2},$tmp{3},$tmp{4}));
print A "$tmp{IP},$token{$tmp{IP}.'.'.$tmp{5}}," if($tmp{5}=~/^m$/i);
print A "$token{$tmp{IP}.'.'.$tmp{5}}\n" if($tmp{5}=~/^u$/i);
}
close(A);
}
##### sub LoadTime
sub LoadTime {
@MONTHLONG=('December','January','February','March','April','May','June','July','August','September','October','November','December');
@MONTHSHORT=('Dec','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
@WEEKLONG=('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday');
@WEEKSHORT=('Sun','Mon','Tue','Wed','Thu','Fri','Sat','Sun');
}
##### sub GetTime
sub GetTime {
($sub{typ},$sub{in})=@_[0,1];
($sub{ss},$sub{mm},$sub{hh},$sub{DD},$sub{MM},$sub{YYYY},$sub{W})=(localtime(time+$sub{in}))[0,1,2,3,4,5,6];
$sub{YYYY}+=1900;
$sub{YY}=substr($sub{YYYY},2,2);
$sub{MM}++;
$sub{$_}=sprintf('%02s',$sub{$_}) foreach('ss','mm','hh','DD','MM');
$sub{typ}=~s/$_/$sub{$_}/ foreach('ss','mm','hh','DD','MM','YYYY','YY','W');
return $sub{typ};
}
##### sub GoExit
sub GoExit {
close(LOG);
exit;
}
i've tested it on both linux redhat 9 and windows 2000 command prompt, both have memory leak just after the ~1600th request, in ~10kb incremental memory usage per request, say it stays steady on ~16MB memory usage before the ~1600th, but this num jumps to ~20MB on the ~2000th
i just don't know why???
any experts out there???
#!/usr/bin/perl -w
##### module usage
use strict;
use Benchmark;
use IO::Socket;
##### declare
our(%token,%cnt,%geo,%cgi,$object,@IP,@MONTHLONG,@MONTHSHORT,@WEEKLONG,@WEEKSHORT);
my(%sub,%tmp,$tmp,@TMP);
##### var
$cgi{db}='/home/lwkstudi/host.lwkstudio.com/db';
##### IO socket, bind & listen
$cgi{object}=new IO::Socket::INET(
LocalHost=>'localhost',
LocalPort=>7890,
Proto=>'tcp',
Listen=>10000,
Reuse=>1);
$cgi{object} or die "no socket :$!";
##### init loading
LoadDB();
LoadToken();
LoadTime();
open(LOG,">>$cgi{db}/geobyip.log");
flock(LOG,2);
##### init success
print "listening on clients\n";
##### accept
while(($object,$cgi{in_ip})=$cgi{object}->accept()){
$cgi{in_sock}=<$object>;
chomp($cgi{in_sock});
L1: for(1){
if($cgi{in_sock}=~/^LoadDB$/i){
LoadDB();
PrintLog("[signal] $cgi{in_sock}");
last L1;
}elsif($cgi{in_sock}=~/^LoadToken$/i){
LoadToken();
PrintLog("[signal] $cgi{in_sock}");
last L1;
}elsif($cgi{in_sock}=~/^(quit|do)$/i){
last L1;
}elsif($cgi{in_sock}=~/^(stop|kill|exit|PrintToken)$/i){
PrintToken();
PrintLog("[signal] $cgi{in_sock}");
GoExit() if($cgi{in_sock}=~/^(kill|exit|stop)$/i);
last L1;
}else{
$cnt{bm_start}=new Benchmark;
$cnt{$_}='' foreach('Token','Port','ErrorMsg','IP','IP10','CountryCode','Country','Time','Benchmark');
($cnt{Year},$cnt{Month},$cnt{Day},$cnt{Hour},$cnt{Minute},$cnt{Second})=split(/\:/,GetTime('YYYY:MM:DD:hh:mm:ss',-3600*8));
$cnt{(split(/\:/))[0]}=(split(/\:/))[1] foreach(split(/\s+/,$cgi{in_sock}));
if($token{$cnt{Token}.'.m'} && $token{$cnt{Token}.'.u'}){
if($token{$cnt{Token}.'.m'}>$token{$cnt{Token}.'.u'}){
$token{$cnt{Token}.'.u'}++;
$cnt{IP10}=$1*16777216+$2*65536+$3*256+$4 if($cnt{IP}=~/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/);
if($cnt{IP10}=~/^[0-9]{8,10}$/){
$cnt{IP10}="0$cnt{IP10}" while(length($cnt{IP10})<10);
$tmp{up}=$cgi{scalarIP};
$tmp{down}=0;
$tmp{last}=0;
while(1){
$tmp{this}=$tmp{up}+$tmp{down};
$tmp{this}=(split(/\./,$tmp{this}/2))[0];
last if($tmp{this} eq $tmp{last});
$tmp{last}=$tmp{this};
($tmp{1},$tmp{2},$tmp{3})=(split(/\,/,$IP[$tmp{this}]))[0,1,2];
if($cnt{IP10}<$tmp{1}){
$tmp{up}=$tmp{this};
}elsif($cnt{IP10}>$tmp{2}){
$tmp{down}=$tmp{this};
}elsif($cnt{IP10}>=$tmp{1} && $cnt{IP10}<=$tmp{2}){
$cnt{CountryCode}=$tmp{3};
chomp($cnt{CountryCode});
last;
}
}
if($cnt{CountryCode}){
$cnt{Country}=$geo{$cnt{CountryCode}};
}else{
$cnt{ErrorMsg}='not found';
}
}else{
$cnt{ErrorMsg}='invalid ip';
}
}else{
$cnt{ErrorMsg}='token quota exceeded';
}
}else{
$cnt{ErrorMsg}='invalid token';
}
$cnt{Benchmark}=$1 if(timestr(timediff(new Benchmark,$cnt{bm_start}))=~/\=\s+([0-9\.]+)\s+CPU\)$/);
PrintLog("[access] $cnt{Token} $cnt{IP} $cnt{Port}");
Output();
undef(%cnt);
}
}
}
##### sub PrintLog
sub PrintLog {
print LOG "$MONTHSHORT[$cnt{Month}] $cnt{Day} $cnt{Hour}:$cnt{Minute}:$cnt{Second} $cnt{Year} $_[0]\n";
}
##### sub Ouput
sub Output {
if($cgi{out_sock}=new IO::Socket::INET(PeerAddr=>'localhost',PeerPort=>$cnt{Port},Proto=>'tcp')){
print {$cgi{out_sock}} <<HTML;
<?xml version="1.0" encoding="UTF-8" ?>
<LwkStudio>
<Server>
<ServerName>xml.geobyip.com</ServerName>
<Token>$cnt{Token}</Token>
<ErrorMsg>$cnt{ErrorMsg}</ErrorMsg>
<Time>$cnt{Time}</Time>
<Benchmark>$cnt{Benchmark} sec</Benchmark>
</Server>
<Request>
<IP>$cnt{IP}</IP>
<IP10>$cnt{IP10}</IP10>
</Request>
<Response>
<CountryCode>$cnt{CountryCode}</CountryCode>
<Country>$cnt{Country}</Country>
</Response>
</LwkStudio>
HTML
close($cgi{out_sock});
}
}
##### sub LoadDB
sub LoadDB {
(@IP,%geo)=undef;
open(A,"$cgi{db}/ip.db");
@IP=<A>;
$cgi{scalarIP}=scalar(@IP);
close(A);
open(A,"$cgi{db}/geo.db");
while(defined($cgi{line}=<A>)){
chomp($cgi{line});
($tmp{1},$tmp{2})=(split(/\,/,$cgi{line}))[0,1];
$geo{$tmp{1}}=$tmp{2};
}
close(A);
}
##### sub LoadToken
sub LoadToken {
undef(%token);
open(A,"$cgi{db}/token.db");
while(defined($cgi{line}=<A>)){
chomp($cgi{line});
($tmp{1},$tmp{2},$tmp{3})=(split(/\,/,$cgi{line}))[0,1,2];
$token{$tmp{1}.'.m'}=$tmp{2};
$token{$tmp{1}.'.u'}=$tmp{3};
}
close(A);
}
##### sub PrintToken
sub PrintToken {
open(A,">$cgi{db}/token.db");
foreach(sort(keys(%token))){
($tmp{1},$tmp{2},$tmp{3},$tmp{4},$tmp{5})=(split(/\./))[0,1,2,3,4];
$tmp{IP}=join('.',($tmp{1},$tmp{2},$tmp{3},$tmp{4}));
print A "$tmp{IP},$token{$tmp{IP}.'.'.$tmp{5}}," if($tmp{5}=~/^m$/i);
print A "$token{$tmp{IP}.'.'.$tmp{5}}\n" if($tmp{5}=~/^u$/i);
}
close(A);
}
##### sub LoadTime
sub LoadTime {
@MONTHLONG=('December','January','February','March','April','May','June','July','August','September','October','November','December');
@MONTHSHORT=('Dec','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
@WEEKLONG=('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday');
@WEEKSHORT=('Sun','Mon','Tue','Wed','Thu','Fri','Sat','Sun');
}
##### sub GetTime
sub GetTime {
($sub{typ},$sub{in})=@_[0,1];
($sub{ss},$sub{mm},$sub{hh},$sub{DD},$sub{MM},$sub{YYYY},$sub{W})=(localtime(time+$sub{in}))[0,1,2,3,4,5,6];
$sub{YYYY}+=1900;
$sub{YY}=substr($sub{YYYY},2,2);
$sub{MM}++;
$sub{$_}=sprintf('%02s',$sub{$_}) foreach('ss','mm','hh','DD','MM');
$sub{typ}=~s/$_/$sub{$_}/ foreach('ss','mm','hh','DD','MM','YYYY','YY','W');
return $sub{typ};
}
##### sub GoExit
sub GoExit {
close(LOG);
exit;
}
