一直想写一个自己的(多线程||多进程)的网络下载程序,就像网络蚂蚁那样的。一直以来有好多瓶颈无法突破。幸运的是从网络上看到一篇perl写的http的断点续传的文章。上面就说,“不知道有没有在写网络蚂蚁之类软件的人呢。”笑~看来我还是幸运的。好了,闲话少说。先贴代码,然后在做注释。希望自己能一步一步达到自己的预期目标。
代码如下:
#!perl!
#socket读取远程文件;
use strict; use IO::Socket qw(:DEFAULT :crlf); #调用IO:Socket模块;
use Errno qw/EINTR/; #摘自大骆驼,用途还没搞懂;
my $blksize = 1024; #设定下载时分块的大小;
my ($host,$port,$path,$written,$buf,$offset);#一些变量;
my $address_new = shift; #命令行读入下载地址;
my $newfile = shift; #要保存的文件名。
#解析地址,提取域名,端口和uri;
($host,$port,$path) = ($1,$2||80,$3) if($address_new =~ m!^(?:http://)?(.*?)(?::([0-9]+))?(/.*)$!x);
print "[$host] [$port] [$path]\n\n";
#下面这段是采用new方法创建连接;
my $socket = IO::Socket::INET->new(
PeerAddr => $host, PeerPort => $port, Type => SOCK_STREAM, Timeout => 20
) or die "Can't connect:$!";
#向下面是向服务器发送http请求;
print $socket "GET $path HTTP/1.1\n"; print $socket "HOST:$host\n"; print $socket "Connection: close\n\n";
open TO,">$newfile"; #使用sysread和syswrite来读入和保存文件。
while (my $len = sysread $socket, $buf, $blksize) { if (!defined $len) { next if $! == EINTR; die "System read error: $!\n" } $offset = 0; while ($len) { $written = syswrite TO, $buf, $len, $offset; die "System write error: $!\n" unless defined $written; $offset += $written; $len -= $written; } }
close TO; close $socket;
|
这么一个简单的脚本学到了很多东西。包括http的协议等,很多都是重新仔细看的。以前没有注意,用到的时候方恨知道的少了。
写这个脚本的时候主要遇到几个问题:
1.一开始老是只能读取html页面(返回200),却不能读出二进制文件(返回400)。找了半天毛病,最后才知道是http的请求构建的有问题。大概对面的服务器不知道我在干嘛。不仔细学习HTTP协议是不行的。
2.如何读取远程文件并写入本地文件。我想这个方法有很多了。但是为了下一步准备,我还是选择了sysread和syswrite的方法。因为我打算用syseek来重定位指针。这样希望可以实现分块下载的目的。而且有些读入和写文件的方法写完的文件是损坏的,不知道是什么问题。可能用法不对。现在这段是摘自大骆驼书上的函数说明里的用法。不知道有没有更简洁的写法。不过这么写确实没有问题。有很多细节还需要消化。还不是很明白。
好久没复习多线程了,下一步希望能通过多线程实现对大文件的分块下载。
要学的东西还很多啊。。。 O(∩_∩)O
by lanmeibanban
2010-08-06
最后附个源码吧~
|
文件: |
net_get.rar |
大小: |
0KB |
下载: |
下载 | |
阅读(1889) | 评论(0) | 转发(0) |