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

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();

 

分享到:
评论

相关推荐

    CurlMulti 一个php多线程类库

    2. **CurlMulti的使用步骤**: - 首先,使用`curl_multi_init()`初始化一个cURL多会话。 - 然后,使用`curl_multi_add_handle()`将需要执行的cURL会话(由`curl_init()`创建)添加到多会话中。 - 接着,调用`curl...

    curl_multi.rar

    为了实现非阻塞I/O,我们可以使用`curl_multi_fdset`来获取需要监视的文件描述符集。然后在主循环中调用`select`或`poll`,等待这些描述符准备就绪。 二、libcurl长连接 2.1 HTTP/1.1长连接 HTTP/1.1引入了Keep-...

    对curlmulti进行简单地封装处理并行请求

    7. **删除已处理的请求**: 请求完成后,使用`curl_multi_remove_handle()`移除处理过的句柄,并通过`curl_close()`关闭单个cURL句柄,释放资源。 8. **清理与结束**: 最后,`MultiCurl`类应该有一个`cleanup()`方法...

    c++ curl multi http post 方式 并发 异步 vs2008

    基于libcurl官网demo,实现http post 并发 ...以文件为介质保存post参数,执行后,将失败链接的参数回存此文件。HandleCurlMulti 以轮询方式进行,可以设置每次的吞吐量。待优化的地方为文件存储,如果多线程需要加锁。

    WWW-Curl-4.15.tar_curl_www_www-curl_Perl_

    **WWW-Curl-4.15.tar - 关于curl、...对于需要在 Perl 环境下使用 `curl` 功能的开发者来说,理解这个库的工作原理和使用方法是非常重要的。同时,选择旧版本的库也需要考虑其与当前系统的兼容性以及新版本的功能更新。

    perl-WWW-Curl-4.17-1.el7.x86_64

    perl-WWW-Curl4.17版本rpm包

    WWW-Curl-4.17.tar_curl_www_www-curl_Perl_

    在 Perl 环境中,要使用 `WWW::Curl` 模块,首先需要通过 CPAN 安装。执行 `cpan WWW::Curl` 即可自动下载并安装。然后在 Perl 脚本中,通过 `use WWW::Curl;` 导入模块,创建 `Curl` 对象并调用其方法发起网络请求...

    PHP使用curl_multi_select解决curl_multi网页假死问题的方法

    为了解决这个问题,我们可以使用 `curl_multi_select` 函数来优化 `curl_multi` 的执行流程。 `curl_multi_exec` 是 `curl_multi` 接口的核心函数,用于执行已添加的所有cURL会话。在示例代码中,原始的 `do......

    curl c++使用

    【标题】:“curl c++使用” 在C++编程中,`curl`库是一个非常重要的工具,它允许开发者通过命令行接口或API实现HTTP、HTTPS和其他网络协议的客户端功能。本篇将详细介绍如何在C++项目中集成和使用`curl`库进行网络...

    php中的curl_multi系列函数用法例子__1.docx

    总的来说,`curl_multi`系列函数在PHP中用于并发执行多个cURL请求,通过合理的使用`curl_multi_init`、`curl_multi_add_handle`、`curl_multi_exec`、`curl_multi_getcontent`、`curl_multi_remove_handle`、`curl_...

    php使用curl_init()和curl_multi_init()多线程的速度比较详解

    在实际应用中,应当根据任务需求和系统资源状况合理选择使用`curl_init()` 或 `curl_multi_init()`。 总结来说,`curl_init()` 和 `curl_multi_init()` 分别适用于不同场景。单个请求或者请求数量较少时,`curl_...

    php中的curl_multi系列函数使用例子

    总的来说,使用`curl_multi`系列函数进行并发请求需要一个循环来监控活动的请求,并在适当的时候调用`curl_multi_exec`和`curl_multi_select`,确保程序在等待数据时能有效地利用资源。理解这些函数的工作原理和正确...

    PHP使用CURL_MULTI实现多线程采集的例子

    这个例子中,通过比较使用`curl_multi`和`file_get_contents`获取相同数量的网页所需的时间,可以明显看出使用CURL_MULTI的性能优势。对于需要处理大量HTTP请求的场景,使用多线程采集可以显著提升程序的运行速度。 ...

    WWW-Curl-4.12.tar_curl_www_www-curl_Perl_

    为了在你的 Perl 环境中使用 WWW-Curl,你需要先解压文件,然后运行 `perl Makefile.PL` 或 `perl Build.PL` 来创建构建文件,接着执行 `make` 或 `./Build` 编译模块,最后使用 `make install` 或 `./Build install...

    PHP用法CURL_MULTI实现多线程采集的例子_.docx

    在一个测试中,使用`CURL_MULTI`从十个不同的网站获取数据只需4.5秒,而使用传统的`file_get_contents()`则需要近33秒,效率提升了约8倍。这种性能提升在处理大量并发请求时尤为明显,特别是在数据采集、爬虫或API...

    curl线程池多线程调用

    在实际操作中,我们可以通过编写脚本或者使用编程语言(如Python、Java等)来调用`curl`,并利用这些语言提供的多线程库来构建线程池。例如,Python中的`concurrent.futures.ThreadPoolExecutor`可以用来创建线程池...

    Curl.zip_C++ curl_DEMO_c++ curl_curl_curl c++

    - CURL库支持多线程,可以同时处理多个请求,使用`curl_multi_init()`和`curl_multi_add_handle()`等函数进行管理。 通过Curl.zip中的DEMO,我们可以看到这些概念如何在实际代码中体现,学习如何将CURL库有效地...

    Qt工程中使用curl进行网络请求,最小程序

    在C++项目中,我们可以使用curl库进行各种网络通信任务。 **Qt框架介绍** Qt是一个跨平台的应用程序开发框架,广泛用于创建GUI应用。它提供了一整套工具、库和IDE,使得开发者能够轻松地构建高效、美观的桌面和移动...

    PHP使用curl_multi实现并发请求的方法示例

    本文将深入讲解如何使用`curl_multi`来实现并发请求,并通过一个具体的示例类`CurlMultiUtil`来演示其实现方法。 首先,`CurlMultiUtil`类中的`getCurlObject`方法用于创建一个CURL会话(`$ch`),根据给定的URL、...

Global site tag (gtag.js) - Google Analytics