`
lht
  • 浏览: 202569 次
  • 来自: 深圳
社区版块
存档分类
最新评论

Perl Curl Multi的使用

阅读更多

Perl利用CURL Multi实现单进程多连接的WEB访问

#!/usr/bin/perl -w

use strict;
use warnings;
use WWW::Curl::Easy;
use WWW::Curl::Multi;

package UrlFetcher;
sub new {
    my $option = shift || {};
    $option->{MAX_CONN} = 2 unless defined($option->{MAX_CONN});
    $option->{CONNECT_TIMEOUT} = 15 unless defined($option->{CONNECT_TIMEOUT});
    $option->{READ_TIMEOUT} = 25 unless defined($option->{READ_TIMEOUT});
    $option->{CB_URL} = sub{} unless defined($option->{CB_URL});
    $option->{CB_RET} = sub{} unless defined($option->{CB_RET});
    $option->{CB_WAIT} = sub {sleep(1)} unless defined($option->{CB_WAIT});
    my $curls = {};
    for (my $i = 1; $i < $option->{MAX_CONN} + 1; $i++) {
        $curls->{$i} = WWW::Curl::Easy->new();
    }
    bless {
        OPTION => $option,
        CURLM => WWW::Curl::Multi->new(),
        IDLE_CURLS => $curls,
        BUSY_CURLS => {},
    }
}

sub DESTROY {
    my $pkg = shift;
    foreach my $i (keys(%{$pkg->{IDLE_CURLS}})) {
        delete $pkg->{IDLE_CURLS}->{$i};
    }
    foreach my $i (keys(%{$pkg->{BUSY_CURLS}})) {
        delete $pkg->{BUSY_CURLS}->{$i};
    }
    delete $pkg->{CURLM};
}

sub _prepareCurl {
    my $pkg = shift;
    my $active_handles = 0;

    foreach my $i (keys(%{$pkg->{IDLE_CURLS}})) {
        my $req = &{$pkg->{OPTION}->{CB_URL}}();
        if (defined($req) && $req) {
            my $curl = $pkg->{IDLE_CURLS}->{$i};
            delete $pkg->{IDLE_CURLS}->{$i};
            my $data = {CURL=>$curl, REQ=>$req};
            $data->{REQ}->{HTTP_CODE} = 0;
            $data->{REQ}->{HTTP_BODY} = '';
            open (my $fileb, ">", \$req->{HTTP_BODY});
            $curl->setopt(WWW::Curl::Easy::CURLOPT_WRITEDATA,$fileb);
            $curl->setopt(WWW::Curl::Easy::CURLOPT_HEADER, 0);
            $curl->setopt(WWW::Curl::Easy::CURLOPT_CONNECTTIMEOUT, $pkg->{OPTION}->{CONNECT_TIMEOUT});
            $curl->setopt(WWW::Curl::Easy::CURLOPT_TIMEOUT, $pkg->{OPTION}->{READ_TIMEOUT});
            $curl->setopt(WWW::Curl::Easy::CURLOPT_URL, $req->{HTTP_URL});
            $curl->setopt(WWW::Curl::Easy::CURLOPT_PRIVATE,$i);
            $pkg->{BUSY_CURLS}->{$i} = $data;
            $pkg->{CURLM}->add_handle($curl);
            $active_handles++;
        }else {
            last;
        }
    }
    return $active_handles;
}

sub __processResult {
    my $pkg = shift;
    my $data = shift;

    &{$pkg->{OPTION}->{CB_RET}}($data);
}

sub perform {
    my $pkg = shift;
    my $active_handles = 0;
    my $pending_handles = $pkg->_prepareCurl();
    $active_handles += $pending_handles;
    while ($active_handles) {
        my $active_transfers = $pkg->{CURLM}->perform();
        if ($active_transfers != $active_handles) {
            while (my ($id,$return_value) = $pkg->{CURLM}->info_read()) {
                if ($id) {
                    $active_handles--;
                    my $data = $pkg->{BUSY_CURLS}->{$id};
                    delete $pkg->{BUSY_CURLS}->{$id};
                    $data->{REQ}->{RET} = $return_value;
                    $data->{REQ}->{HTTP_CODE} = $data->{CURL}->getinfo(WWW::Curl::Easy::CURLINFO_HTTP_CODE);
                    $pkg->__processResult($data->{REQ});
                    $pkg->{IDLE_CURLS}->{$id} = $data->{CURL};
                }
            }
        }
        $pending_handles = $pkg->_prepareCurl();
        &{$pkg->{OPTION}->{CB_WAIT}}() unless ($pending_handles);
        $active_handles += $pending_handles;
        die("bad items of easy curl") unless ($pkg->{OPTION}->{MAX_CONN} == scalar(keys(%{$pkg->{IDLE_CURLS}})) + scalar(keys(%{$pkg->{BUSY_CURLS}})));
    }
}

1;
__END__

=head1 DOCUMENTATION

use UrlFetcher;
$i = 0;
sub cb_url {
    my $ret = undef;
    $i++;
    $ret = {HTTP_URL => 'http://192.168.2.150/lht/lht.txt?idx='.$i, IDX => $i, MY_VALUE => '000',};
    sleep(5) unless ($i % 20);
    return $ret;
}

sub cb_ret {
    my $d = shift;
    print 'INDEX: '. $d->{IDX}. "\n";
    print 'MY VALUE: '. $d->{MY_VALUE}. "\n";
    print 'RET CODE: '. $d->{RET}. "\n";
    if ($d->{RET}) {
        print "RET MSG: BAD\n";
    } else {
        print "RET MSG: OK\n";
    }
    print 'HTTP CODE: '. $d->{HTTP_CODE}. "\n";
    print 'HTTP BODY: '. $d->{HTTP_BODY}. "\n";
}

sub cb_wait {
    sleep(1);
}

my $opt = {MAX_CONN=>10,
           CONNECT_TIMEOUT=>25,
           READ_TIMEOUT=>35,
           CB_URL=>\&cb_url,
           CB_RET=>\&cb_ret,
           CB_WAIT=>\&cb_wait,
           };
my $fetcher = UrlFetcher::new($opt);
$fetcher->perform();

 

分享到:
评论

相关推荐

    Asterisk常用命令

    7. **Perl**: 使用Perl脚本。 8. **PHP**: 使用PHP脚本。 9. **Read**: 通过DTMF读取变量值。 10. **TXTCIDName**: 从TXT记录中查找来电者姓名。 11. **UserEvent**: 发送自定义事件给监控程序。 #### 控制流与时限...

    CentOS6.7下使用非root用户(普通用户)编译安装与配置mysql数据库并使用shell脚本方式实现数据库随机自动启动

    devel pam-devel openssl-devel libxml2-devel gettext-devel pcre-devel net-snmp-devel curl-devel perl-DBI vixie-cron crontabs wget ``` **2.2 检查并卸载已存在的 MySQL 服务** 确保系统中没有安装任何版本...

    nginx linux版本安装源码nginx-1.21.6.tar

    2. **编译前准备**:在编译源码之前,确保系统中安装了必要的依赖库,如`pcre`(Perl Compatible Regular Expressions)、`openssl`和`zlib`。使用以下命令安装: ```bash sudo apt-get update # 更新软件包列表 ...

    服务器:EQEmu-开源EverQuest服务器

    EQEmulator核心服务器 ...您可以使用curl或wget启动安装程序(以您的操作系统为准) curl -O install.sh && chmod 755 install.sh && ./install.sh wget --no-check-certificate -O install.sh &&

    [修复下载链接]iPhone5S和iPad4上编译C/C++

    curl 7.33.0-8 flexible multi-protocol file transfers gdb 1821 debugger + debugserver 300.2 for iOS git 1.5.6.rc0-2p fast content-addressable filesystem iphone-gcc 4.2-20080604-1-8p a native c ...

    php中文完全开发手册

    CURL, Client URL Library Functions XIII. Cybercash Payment Functions XIV. Cyrus IMAP administration Functions XV. Character Type Functions XVI. Database (dbm-style) Abstraction Layer Functions XVII. ...

    MySQL 5.6 Reference Manual

    Table of Contents Preface, Notes, Licenses . . . . . . . . ....1. Licenses for Third-Party Components ....1.1. FindGTest.cmake License ....1.2. LPeg Library License ....1.3. LuaFileSystem Library License ....

Global site tag (gtag.js) - Google Analytics