2. CPU的占用率 CPU的占用率就是指程序运行后,文件传输时CPU的使用情况。CPU主要工作在文件数据的读写,文件数据的压缩与解压缩。文件数据连续的进行写入内 存,或者从内存写入文件都会占用很多的CPU使用,压缩解压缩数据时,对于很大的数据进行压缩或解压缩也会占用很大的CPU使用。 想要降低CPU占用率,就要使文件发送与接收有层次,将大的数据分开成若干的较大的数据包,然后再将这些数据包分别按小包发送。如何控制分割的大数据包 的大小,和每次发送数据包的大小,与接收端接收了多少数据再写入文件都是关键,;如果要对传输的数据进行压缩,何时进行压缩和解压缩,一次压缩和解压多 少数据,压缩次数是关键,由于逻辑结构的因素,何时进行压缩就制约了数据压缩大小,在文件分割前压缩,压缩的数据就会很大,如果把文件分割成大的数据包 后进行压缩,这个数据包的大小就决定压缩的效率,如果在每次SOCKET发送数据包的时候进行压缩,就会使压缩的次数巨增,也制约了压缩效率。 3. 网络资源的使用率 网络资源的利用率是指在文件传输过程中,对网络资源的利用情况,SOCKET在传输数据包的时候有一个最大传输字节,可以用 SND_BUF、RCV_BUF分别取出发送端与接收端的最大值。每次发送数据包时候最大利用了SND_BUF、RCV_BUF的大小,就可以使传输效 率大大提高,网络利用率也就很高。网络资源的使用率也影响文件数据的传输速率。为了保证每次发包与收包的数据大小的一致性,我们就要保证 SND_BUF、RCV_BUF的一致,所以接收端的RCV_BUF要与发送端的SND_BUF相等,这就要求我们在发送文件之前的通信中要把发送端的 SND_BUF告诉接收端,接收端对自己的RCV_BUF进行处理。 文件传输过程中还有一些问题: 1.文件传输结束标志,文件什么时候传输完毕,我们退出SOCKET,不再进行数据的收发,我们可以在传输前通信前的通信中把文件大小告诉接收方,当接 收方写入文件数据到了该大小后传输结束。 2.文件传输过程中出现发送方与接收方单方中断传输时候,要通知对方结束程序,并对没有写完的文件进行删除,着块要根据传输方式跟逻辑结构的不同采取不 同的方法实现。 3.文件内容的压缩与不压缩一定程度上影响了文件传输的逻辑结构,采取不同的压缩方式,在不同的阶段进行压缩,文件传输的逻辑结构应该不同,这样才能保 证传输数据的正确性和传输的高效性。 4.在文件传输过程中是否会有丢包的现象呢?采取TCP方式,由于它是可靠的连接,三次握手机制保证了传输数据的正确性。而采取UDP方式就不行了。另 外接收端在采用sysread从SOCKET中读数据时候,如果是外网文件传输,sysread会出现读到的数据小于我们指定的长度,这样就要采取逻辑 上的补救,限制读够了该长度后才读下一数据。 5.文件接收端在往缓存变量写数据时候,如果一次写入的数据比较大,那么,第一次写数据时候将消耗大量的时间,这里要采用先把缓存扩大到数据长度的空间 大小,然后清空缓存变量,再进行数据的写入。 6.数据压缩后发送给接收端,接收端如何知道何时解压缩得到的数据是原始正确的数据呢,压缩后的数据分开后或者取出部分后解压缩后得到的值肯定不等于原 始数据,接收端依次读取SOCKET数据包,累加写入变量,当变量的值等于发送端发送的压缩数据时,对其解压缩得到的值才是原始数据。判断这个变量等于 压缩的数据就要用到压缩数据的大小,发送端压缩后先与接收端进行通信,将压缩数据大小告诉接收端,接收端反馈一个收到的信息后,发送端开始发送压缩数 据,接收端根据收到的压缩数据的大小来判断接收数据是否到达了压缩数据包的大小,如果大小一样了,就说明压缩包全部接收到了,现在就可以进行解压缩处理 了。
总结,一个基本的文件传输结构已经出来了,再加上简单的处理,比如,对发送文件的选择,接收文件的重命名,传输方的IP选择等等,文件传输程序就基本实 现了,程序还有很多不太合理的地方,CPU,网络,跟传输速率还有提升的空间,希望大家批评指正。
附:程序雏形的代码: 接收端代码: use strict; use IO::Socket; use IO::Select; use Socket; use Compress::Zlib ;
my $port=2008; my ($input,$no,$temp,$num,$n,$head,$input1,$input2,$i,$u,$z,$length, $head,$r); $z=0; $num=10000; #my $length=1400; $input1=’a’x90000000; $input1=”; $temp=’a’x90000000; $temp=”; my $file=”34567.exe”; open(FILE,”>$file”); binmode FILE; my $sock = IO::Socket::INET->new( Listen => 20, LocalPort => $port, Proto =>’TCP’, Reuse => 1) or die “Can’t create listening socket: $!n”; print “recv sever is connect now!n”; #创建一个服务器进行监听。
$no=1;
#确定保存文件全路径名并打开文件 my $session = $sock->accept(); my $select=IO::Select->new($session); my $rr; print “文件接收中…n”;
###########接收文件前的通信:依次按读出的长度读出 文件名 文件长度 SNDBUFF #################### my ($l0,$l1,$l2,$l3,$cmd,$filename,$u,$buf,$info); while(1){ if ($select->can_read()) { if($session->recv($info,10000,0)) { $l0=substr($info,0,1); $l0=unpack(“c”,$l0); #print $l0.”n”; $cmd=substr($info,1,$l0); $l1=substr($info,$l0+1,1); $l1=unpack(“c”,$l1); #print $l1.”n”; $filename=substr($info,$l0+2,$l1); #print $filename.”n”; $l2=substr($info,$l0+$l1+2,1); $l2=unpack(“c”,$l2); #print $l2.”n”; $u=substr($info,$l0+$l1+3,$l2); #print $u.”n”; $l3=substr($info,$l0+$l1+$l2+3,1); $l3=unpack(“c”,$l3); #print $l3.”n”; $buf=substr($info,$l0+$l1+$l2+4,$l3); #print $buf.”n”; $buf=pack(“I”, $buf); setsockopt($sock, SOL_SOCKET, SO_RCVBUF, $buf); $length=getsockopt($sock,SOL_SOCKET,SO_RCVBUF); #print $length,”n”; $length=unpack(“I”, $length); $session->send(“BEGIN”);last; }
while (1){ ##################### ##################### ##################### #################### ##################### if ($select->can_read()) { unless($filename=~/.exe$/i or $filename=~/.zip$/i or $filename=~/.rar$/i ) { while(1) { if( $session->recv($head,$length,0)) { #print “$headn”; $head=hex(substr(unpack(“H*”,$head),0,8)); #print “$headn”; $session->send(“START”);last;} } } RE: $r=sysread $session,$input,$length; #print “$nn”;
$input1.=$input; $i=length $input1; #print $i.” “.$head.”n”; unless($filename=~/.exe$/i or $filename=~/.zip$/i or $filename=~/.rar$/i ) {unless($i eq $head){goto RE;}} unless($filename=~/.exe$/i or $filename=~/.zip$/ i or $filename=~/.rar$/i ) {$input1=uncompress($input1);} $z+=$i; #print $z.”n”; $temp.=$input1; unless($filename=~/.exe$/i or $filename=~/.zip$/i or $filename=~/.rar$/i ) { } else { if($no%$num==0) { print FILE $temp; $temp=””; } }
if ($z eq $u) { if($filename=~/.exe$/i or $filename=~/.zip$/i or $filename=~/ .rar$/i ) {print FILE $temp; } close(FILE); shutdown $session,2; print “接收完毕n”; exit(0); }
$no++; $input=””;$input1=””; unless($filename=~/.exe$/i or $filename=~/.zip$/i or $filename=~/.rar$/i ) {$temp=””;}
##################### ##################### ##################### ##################### ##################### }
发送端代码: use strict; use IO::Socket; use IO::Select; use Socket; use Compress::Zlib ;
my $ss; my $mm; my $hh; my $n;my $t;my $w; my ($host,$port,$line,$f,$sock,$head,$headpack,$sum1); print “####飞鸽传书模拟版,文件发送端###n”;
$host=”192.168.1.100″;#124.128.127.15 192.168.1.101 $port=2008; #确定主机地址
my $path=”123.exe”; #确定传送文件 &start_sock;
sub start_sock {$sock=new IO::Socket::INET(PeerAddr=>$host, PeerPort=>$port, Proto =>’TCP’ ) or die “connect err”; my $select=IO::Select->new($sock); my $l =getsockopt($sock,SOL_SOCKET,SO_SNDBUF);
$l=unpack(“I”, $l);
my $length=$l*1000;#可以改变大小(每一大块数据的大小) print “sock creat ok!n”; my $time= scalar(localtime); print “开始发送时间:”.$time.”n”; $time=substr($time,11,8); my @time=split/:/,$time; my $h=$time[0]; my $m=$time[1]; my $s=$time[2]; #取时间
print “开始发送…n”; my $session; my $input;
my $f_content; open(FILE,$path) or die “open file err”; my $no=1; my $sum; binmode FILE; my $size = (stat($path))[7]; #print $size.”n”; if ($size%$length==0) { $sum=$size/$length; } else { $sum=int($size/$length+1); } # 取文件大小,确定发送数据包的个数
###########接收文件前的通信:依次发送: 命令长度, 命令行(以后扩展用), 文件名长度, 文件名, 文件大小长度, 文件大小, SENDBUFFER长度, SENDBUFFER.#################### my $cmd=”0000″;#定义命令 以后扩展 my $length0=length $cmd;#命令长度 以后扩展 $length0=pack(“c”,$length0); my $length1=length $path; $length1=pack(“c”,$length1); my $length2=length $size; $length2=pack(“c”,$length2); my $length3=length $l; my $length3=pack(“c”,$length3); print $sock $length0.$cmd.$length1.$path.$length2.$size.$length3.$l; AA:if ($select->can_read()) { sysread $sock,$input,5; if($input eq “BEGIN”){goto CC;} else{ goto AA;} } else{ goto AA;} #####################################组织发送数据:发送数据包的格式: 压缩数据大小 ################################################### ########压缩数据方式:把原始数据分成很多较大的数据包,每一个大的数据包进行压缩 CC: foreach (1..$sum){ sysread FILE,$f_content,$length; $w=0; unless($path=~/.exe$/i or $path=~/.rar$/i or $path=~/.zip$/i) {$f_content=compress($f_content); $head=length $f_content; #print “$headn”; $headpack=pack(“N2”,$head); print $sock $headpack; BB:if ($select->can_read()) { sysread $sock,$input,5; if($input eq “START”){goto DD;} else{ goto BB;} } else{ goto BB;} DD: if ($head%$l==0) { $sum1=$head/$l; } else { $sum1=int($head/$l+1); } } else{$sum1=($length/$l);} foreach(1..$sum1){ my $no1= pack(“N2”,$no); if(!(substr($f_content,(0+$w*$l),$l))) {last;} print $sock substr($f_content,(0+$w*$l),$l);#发送数据 #print “send : “.substr($f_content,0+$w*$l,1).substr($f_content,0+ $w*$l+1300,1).”n”; $w++; $no++; } #print “发送完毕n”;
}
################################################################################################## #print “传送完毕n”; my $time1= scalar(localtime); print “发送完毕时间:”.$time1.”n”; $time1=substr($time1,11,8); my @time1=split/:/,$time1; my $h1=$time1[0]; my $m1=$time1[1]; my $s1=$time1[2]; #取发送完毕的时间
if($s1 >= $s) {$ss=$s1-$s;} else {$s1+=60;$ss=$s1-$s;$m1–;}
if($m1 >= $m) {$mm=$m1-$m;} else {$m1+=60;$mm=$m1-$m;$h1–;}
if($h1 >= $h) {$hh=$h1-$h;} else {$h1+=24;$hh=$h1-$h;} print “发送消耗时间:$hh小时$mm分$ss秒n”; #计算消耗时间 my $ts=$mm*60+$ss; eval{print “平均”.($size/$ts)/(1024*1024).”M/sn”;};
close(FILE); shutdown $sock,2;
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/82392/viewspace-442694/,如需转载,请注明出处,否则将追究法律责任。
主题测试文章,只做测试使用。发布者:布吉卡,转转请注明出处:http://www.cxybcw.com/195787.html