`
shaojiashuai123456
  • 浏览: 262154 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
社区版块
存档分类
最新评论

libevent作为客户端

 
阅读更多

         libevent通常作为服务端,但是有场景会作为客户端去抓取别的服务,通常可以使用libcurl去抓取,但是会使整个线程处于等待状态,这时可以使用libevent客户端模式,使请求完全异步。

 

    

#ifndef _EVENT_CURL_H_
#define _EVENT_CURL_H_

#include <string>

using namespace std;

typedef void (*RequestFinishHandler)(struct evhttp_request *req, void *arg);

struct event_base;

class EventHttpReq
{
public:
    EventHttpReq()
    {
        m_time_out = 300;
        finish_handler = NULL;
        finish_arg = NULL;
    }

    string m_url;
    string m_post_data;
    int m_time_out;
    RequestFinishHandler finish_handler;
    void *finish_arg; 
};

class EventCurl
{
public:
   static bool curl(EventHttpReq &eventHttpReq, struct event_base *, struct evhttp_connection *& conn);
};



#endif

 

 

 

#include <signal.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include "EventCurl.h"
#include "event2/util.h"
#include "event2/http.h"
#include "event2/http_struct.h"
#include "event2/buffer.h"


bool EventCurl::curl(EventHttpReq &eventHttpReq, struct event_base *base, struct evhttp_connection *& conn)
{
    struct evhttp_request *req;

    const char *scheme, *host, *path, *query;
    struct evhttp_uri *http_uri = evhttp_uri_parse(eventHttpReq.m_url.c_str());
    if (NULL == http_uri)
    {
        return false;
    }
    string uri;
    int port;
    scheme = evhttp_uri_get_scheme(http_uri);
    if (scheme == NULL || (strcasecmp(scheme, "https") != 0 &&
                              strcasecmp(scheme, "http") != 0)) 
    {
        evhttp_uri_free(http_uri);
        return false; 
    }

    host = evhttp_uri_get_host(http_uri);
    if (NULL == host)
    {
        evhttp_uri_free(http_uri);
        return false;
    }

    port = evhttp_uri_get_port(http_uri);
    if (port == -1)
    {
        port = (strcasecmp(scheme, "http") == 0) ? 80 : 443;
    }

    path = evhttp_uri_get_path(http_uri);
    if (path == NULL || strlen(path) == 0)
    {
        uri = "/";
    }
    else
    {
        uri = path;  
    }

    query = evhttp_uri_get_query(http_uri); 
    if (query != NULL)
    {
        uri += "?";
        uri += query;
    }

    conn = evhttp_connection_base_new(base, NULL, host, port);
    if (NULL == conn)
    {
        evhttp_uri_free(http_uri);
        return false;
    }
    req = evhttp_request_new(eventHttpReq.finish_handler, eventHttpReq.finish_arg);
    if (NULL == req)
    {
        evhttp_connection_free(conn);
        evhttp_uri_free(http_uri);
        conn = NULL;
        return false;
    }
    evhttp_add_header(req->output_headers, "Host", host);
    int make_request_ret = 0;
    if (eventHttpReq.m_post_data.size() > 0)   //post请求,则加入post的内容
    {
        evbuffer_add(req->output_buffer, eventHttpReq.m_post_data.c_str(), eventHttpReq.m_post_data.size());
        make_request_ret = evhttp_make_request(conn, req, EVHTTP_REQ_POST, uri.c_str());
    }   
    else                                  //get请求
    {
        make_request_ret = evhttp_make_request(conn, req, EVHTTP_REQ_GET, uri.c_str());
    }

    if (make_request_ret != 0)
    {
        evhttp_connection_free(conn);
        evhttp_request_free(req);
        evhttp_uri_free(http_uri);
        conn = NULL;
        return false;
    }
    evhttp_connection_set_timeout(req->evcon, eventHttpReq.m_time_out);
    evhttp_uri_free(http_uri);

    return true;
}

 

 

 

    收到返回结果,或异常时的处理。

void  finish_handler(struct evhttp_request *req, void *arg)
{
   EParser *parser = (EParser *)arg;
   
   parser->m_curl_time = parser->m_timer.ElapseTime();

   int http_code = 0;
   if (req != NULL)
   {
       http_code = evhttp_request_get_response_code(req);    //http码
       parser->m_http_code = http_code;
       if (http_code == HTTP_OK)
       {
           int s = evbuffer_remove(req->input_buffer, &parser->curl_result, E_MAX_SIZE_BUF);
           struct evkeyvalq* headers = evhttp_request_get_input_headers(req);  //http头部
           for (evkeyval* header = headers->tqh_first; header != NULL; header = header->next.tqe_next)
           {
               parser->m_receive_header.insert(std::pair<string, string>(header->key, header->value));
           }
       }
   }

   parser->m_is_finish = true;
   ProcessRequestSend(EParser);
}

 

 

 

分享到:
评论

相关推荐

    libevent服务器和客户端

    这些文件可以作为学习和参考的实例,通过阅读和运行代码,可以更好地理解libevent的使用方法。 总结,libevent是一个强大的工具,它简化了网络编程中的事件处理,使得开发者能更专注于业务逻辑。这个项目提供了一个...

    libevent创建客户端&服务端demo

    1. 初始化libevent:在程序启动时,你需要调用`event_base_new()`函数来创建一个事件基础结构,这将作为所有事件处理的中心。 2. 注册事件:对于网络I/O事件,如TCP连接,我们可以使用`event_new()`创建一个新的...

    livevent在MFC上的实现

    最终选择了比较强健并且夸平台的libevent作为主要实现目标(当然其他的也都有实现, 主要实现的还有libuv和netty), 并用于做TCP服务程序工具。希望能给大家帮助。另外看到也有朋友要用MFC来实现的, 正好给他们参考...

    【最新】C++ 使用libEvent实现http的post, get功能

    这个函数需要基础事件结构体作为参数,返回一个HTTP客户端句柄。 3. **配置HTTP请求**:对于GET请求,可以直接指定URL;而对于POST请求,需要额外设置HTTP头信息,指定请求方法为POST,并提供数据。可以使用`...

    最新版linux fastdfs libevent-2.1.11-stable.tar.gz

    总结起来,Linux FastDFS结合libevent-2.1.11-stable可以构建一个高性能的分布式文件系统,libevent作为底层的事件驱动库,为FastDFS提供了强大的网络通信支持,使系统在处理大量并发连接时保持高效和稳定。...

    libevent-2.1.12-stable.tar.gz

    libevent-2.1.12-stable作为libevent库的一个稳定版本,不仅提供了跨平台的事件处理机制,还通过持续优化提升了性能和易用性。理解和掌握libevent的使用,对于提升网络编程的效率和质量具有重要的意义。开发者可以...

    libevent2.0.4 for linux

    1. **libevent核心概念:**libevent提供了一个事件基础架构,可以将事件模型(如 epoll、poll、select)与各种网络协议(如TCP、UDP、Unix域套接字)结合,简化了编写高性能网络服务器和客户端的工作。 2. **事件...

    libevent最新静态库

    Libevent作为一个强大的事件库,为开发者提供了在Windows环境下构建高性能网络服务的便利。通过理解和熟练使用libevent,可以极大地提高程序的并发处理能力和响应速度。配合提供的静态库和头文件,开发者可以直接在...

    libevent-1.4.11-stable.tar.gz

    Libevent作为一个强大的事件库,为开发者提供了简洁的API,使得编写高性能、高并发的网络服务成为可能。在PHP环境中,正确理解和使用libevent,可以显著提升服务器的处理能力,为互联网应用提供更加流畅的服务体验...

    libevent 注释

    libevent 是一个开源、跨平台的事件通知库,它允许程序员编写高性能、异步的网络服务器和客户端程序。在本文中,我们将深入探讨 libevent 的核心概念、功能特性、使用场景以及如何进行实际编程。 ### 1. libevent ...

    libevent-2.1.8 + event-2.3.0.zip

    2. 监听套接字:使用libevent或event的监听函数创建一个监听套接字,用于接收新的客户端连接。 3. 处理连接:当有新的连接到达时,注册对应的读事件,处理客户端发送的数据。 4. 发送响应:在收到数据后,根据业务...

    在X86上libevent的简单使用.docx

    与传统的基于线程或进程的并发模型相比,`libevent`通过事件循环机制实现了更为高效的任务调度,特别适用于需要处理大量客户端连接的服务器应用。`libevent`支持多种操作系统,包括Linux、BSD变种以及Windows等。 #...

    libevent的vs2013工程

    例如,你可以创建一个简单的服务器或客户端来测试Libevent的功能。完成后,点击工具栏上的“生成”按钮编译项目。如果一切顺利,你应该能在“输出”窗口看到编译成功的消息。如果遇到错误,检查配置是否正确,或者...

    libevent中文参考手册

    ### libevent中文参考手册...总之,libevent作为一个强大的跨平台异步IO库,旨在简化网络编程的同时保持高性能和灵活性。无论是对于构建高性能Web服务器还是开发复杂的企业级应用,libevent都是一个值得考虑的选择。

    C++ vs2015 x64编译使用libevent 测试项目

    在“配置管理器”中,选择“x64”作为目标平台,然后进行编译和调试。 总结,使用libevent进行C++开发涉及了库的配置、事件基础的创建、事件的添加与删除,以及事件回调函数的编写。通过理解和实践这些知识点,你...

    VS2008调试libevent1.2.8

    这个库特别适用于编写高性能、可扩展的网络服务器或客户端,因为它能够有效地处理大量的并发连接。 **1. 安装和配置VS2008** 首先,确保你已经安装了Microsoft Visual Studio 2008。如果没有,可以从微软官方网站...

    使用 libevent 和 libev 提高网络应用性能的方法

    libevent 作为一种事件驱动的解决方案,其核心在于提供了对底层网络后端的高效封装。它不是替换原有的系统调用如 `select()` 或 `poll()`,而是在这些基础之上添加了一层高级抽象,使得用户可以更加专注于业务逻辑而...

    libevent for android

    Android系统作为基于Linux内核的移动操作系统,理论上可以支持Libevent。然而,由于Android的环境与标准Linux有所不同,因此需要对Libevent进行一定的修改和配置才能使其在Android上正常运行。这通常涉及到NDK...

    libevent.rar

    作为TCP server如果耗时操作处理得当实测能够稳定在线10000+客户端。无内存泄露,相比其他开源网络库,cpu、内存占用更低。具体TCP SERVER使用方式参考LibeventServer.cpp,也可以联系本人交流。

Global site tag (gtag.js) - Google Analytics