- 论坛徽章:
- 0
|
本帖最后由 zhlong8 于 2013-04-19 15:10 编辑
请教各位大神:我想做一个文件服务器,用PERL SOCKET实现文件下载,源码如下,我的服务器端,进程在运行的过程中内存越占越多,请教有没有好的内存回收方法?
刚开始后占同存如下:
请求下载一个104MB的文件后
请求下载一个379mb的文件后
再请求下载一个104MB的文件后
下面是源码,请求各位帮助。谢谢!
服务端:
#!/usr/bin/perl
#Poster.pl
use Socket;
use IO::Socket::INET;
use IO::Select;
use strict;
while(1){
my $file;
my $server = IO::Socket::INET->new( LocalPort => 9000,
Listen => 5,
Proto => 'tcp')
or die "Couldn`t be a tcp server on port: 9000 :$@\n";
#接收远程需求
my $sel = IO::Select->new($server);
while (my @ready = $sel->can_read) {
foreach my $fh (@ready) {
#print "$fh == $server \n";
if ($fh == $server) {
my $new = $server->accept();
$sel->add($new);
}
else {
$fh->recv($file,1024,0); #接收客户端消息
# print "$file 435345\n";
if (-e "$file") {
$fh->send("$file 存在,数据传输送开始 OK!\n",0); #发送服务端消息
}
$fh->autoflush(1);
$sel->remove($fh);
$fh->close();
if (-e "$file") {
close ($server);
&senddata("$file");
open (F_L,">c:/tcp.log");
print F_L "$file\n";
close(F_L);
}
}
$fh = undef;
}
}
close ($server);
$sel=undef;
$server=undef;
}
sub senddata {
my ($file) = @_;
print "$file senddata \n";
#发送端代码
#创建一个套接字,定义最大连接数为5,本地端口为9000,链接协议为tcp
my $server = IO::Socket::INET->new( LocalPort => 9000,
Listen => 5,
Proto => 'tcp')
or die "Couldn`t be a tcp server on port: 9000 :$@\n";
#等待远程连接
while( my ($client,$client_IP) = $server->accept()){
my($port,$packed_ip) = sockaddr_in($client_IP);
my $ip = inet_ntoa($packed_ip);
print "有客户端:< $ip >连接上,准备传输数据....\n";
#打开指定文件
open IN,"<$file";
#以二进制形式操作
binmode(IN);
#与客户端建立连接后,以二进制形式读取文件数据,向套接字发送数据
my @out = <IN>;
print $client @out;
close IN;
close ($server);
};
$server = undef;
print "数据传输完毕\n";
}
客户端:
#!/usr/bin/perl -w
use IO::Socket; ##IO::Socket::INET模块是IO::Socket模块的子模块,不用重新use。
use IO::Select; ##该模块和Linux下select()函数实现的功能一致,另扩展更过的功能。可以perldoc查看。
# hash to install IP Port
%ser_info = (
"ser_ip" => "127.0.0.1",
"ser_port" => "9000",
);
my $inputfile = $ARGV[0];
my $outfile = $ARGV[1];
&main();
#&maintest(); #接收返回信息
#&mainq();
sub mainq {
my $files1;
my $ser_addr = $ser_info{"ser_ip"};
my $ser_port = $ser_info{"ser_port"};
##IO::Socket::INET->new()用于初始化一个socket连接,其中集成了socket、inet_aton、connect、bind、listen等功能。就不需要单独转换IP地址为网络地址结构了,直接使用IP地址就ok了。
##具体参数下面单独介绍。
my $socket = IO::Socket::INET->new(
PeerAddr => "$ser_addr",
PeerPort => "$ser_port",
Type => SOCK_STREAM,
Proto => "tcp",
)
or die "Can not create socket connect.$@";
if($socket){
#当连接建立
print"连接上了远程主机:$ser_addr,准备接收数据\n";
my @Receive = <$socket>;
open(OUT,">$files1");
binmode(OUT);
print OUT @Receive;
close OUT;
}
# close($socket);
print"数据接收完毕\n";
print "test \n";
}
sub main {
my $ser_addr = $ser_info{"ser_ip"};
my $ser_port = $ser_info{"ser_port"};
my $file_exists = 'no';
##IO::Socket::INET->new()用于初始化一个socket连接,其中集成了socket、inet_aton、connect、bind、listen等功能。就不需要单独转换IP地址为网络地址结构了,直接使用IP地址就ok了。
##具体参数下面单独介绍。
my $socket = IO::Socket::INET->new(
PeerAddr => "$ser_addr",
PeerPort => "$ser_port",
Type => SOCK_STREAM,
Proto => "tcp",
)
or die "Can not create socket connect.$@";
$socket->send("$inputfile",0); ##发送消息至服务器端。
$socket->autoflush(1);
my $files1 = "$outfile";
print "$socket ok\n";
# $socket->autoflush(1);
# print "$socket \n";
my $sel = IO::Select->new($socket); ##建立select对象
while (my @ready = $sel->can_read) { ##等待服务端返回的消息
foreach my $fh (@ready) {
if ($fh == $socket) {
while (<$fh>) {
print $_;
if (length($_) > 0) {
$file_exists = 'yes';
}
}
$sel->remove($fh);
close $fh;
#close $;
}
}
}
close($socket);
if ($file_exists eq 'yes') {
&maintest();
}
# $socket->close() or die "Close Socket failed";
}
sub maintest {
$file = "$outfile";
my $host = $ser_info{"ser_ip"};
my $socket = IO::Socket::INET->new(PeerAddr => $ser_info{"ser_ip"},
PeerPort => 9000,
Proto => 'tcp')
or die "Couldn`t connect to $host:9000\n";
if($socket){
#当连接建立
print"连接上了远程主机:,准备接收数据\n";
my @Receive = <$socket>;
open(OUT,">$file");
binmode(OUT);
print OUT @Receive;
close OUT;
}
close($socket);
print"数据接收完毕\n";
} |
|