libevent evhttp多线程
Posted byxdaz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了libevent evhttp多线程相关的知识,希望对你有一定的参考价值。
一、多线程流程:
1、创建socket,绑定port
2、多线程,每个线程申请event_base和evhttp,通过evhttp_accept_socket绑定。
int evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)使http server可以接受来自指定的socket的连接,可重复调用来绑定到不同的socket。
(1)http为待绑定的http server指针
(2)fd为待绑定的socket(该socket应已准备好接受连接) 0表示成功,-1表示失败
跟此函数类似的一个函数为evhttp_accept_socket_with_handle,其声明是struct evhttp_bound_socket *evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd); 与evhttp_accept_socket唯一不同的地方是返回值不同,它返回了一个socket句柄
二、http server多线程代码
#include <event.h>
#include <evhttp.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <vector>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <event2/keyvalq_struct.h>
#include <event2/thread.h>
int httpserver_bindsocket(int port, int backlog);
int httpserver_start(int port, int nthreads, int backlog);
void* httpserver_Dispatch(void *arg);
void httpserver_GenericHandler(struct evhttp_request *req, void *arg);
void httpserver_ProcessRequest(struct evhttp_request *req);
evutil_socket_t httpserver_bindsocket(int port, int backlog)
int rt;
evutil_socket_t sock
sock= socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
perror("could not create socket");
return -1;
rt = evutil_make_listen_socket_reuseable(sock);
if (rt < 0)
perror("cannot make socket reuseable");
return -1;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
rt = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
if (rt < 0)
perror("cannot bind socket");
return -1;
rt = listen(sock, 1024);
if (rt < 0)
perror("cannot listen");
return -1;
rt = evutil_make_socket_nonblocking(sock);
if (rt < 0)
perror("cannot make socket non blocking");
return -1;
return sock;
int httpserver_start(int port, int nthreads, int backlog)
evthread_use_pthreads(); //ok if called from other places
std::vector<base *> vecBase;
int r, i;
evutil_socket_t nfd = httpserver_bindsocket(port, backlog);
if (nfd < 0) return -1;
pthread_t ths[nthreads];
for (i = 0; i < nthreads; i++)
struct event_base *base = event_init();
if (base == NULL) return -1;
vecBase.push_back(base);
struct evhttp *httpd = evhttp_new(base);
if (httpd == NULL) return -1;
r = evhttp_accept_socket(httpd, nfd);
if (r != 0) return -1;
evhttp_set_gencb(httpd, httpserver_GenericHandler, NULL);
r = pthread_create(&ths[i], NULL, httpserver_Dispatch, base);
if (r != 0) return -1;
for (i = 0; i < nthreads; i++)
pthread_join(ths[i], NULL);
//exit
for (i = 0; i < nthreads; i++)
event_base_loopbreak(vecBase[i]);
evutil_closesocket(nfd);
void* httpserver_Dispatch(void *arg)
event_base_dispatch((struct event_base*)arg);
return NULL;
void httpserver_GenericHandler(struct evhttp_request *req, void *arg)
httpserver_ProcessRequest(req);
void httpserver_ProcessRequest(struct evhttp_request *req)
struct evbuffer *buf = evbuffer_new();
if (buf == NULL) return;
//here comes the magic
int main(void)
httpserver_start(8081, 10, 10240);
三、http client代码
#include <event2/event_struct.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/http.h>
#include "evhttp.h"
int init_win_socket()
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return -1;
return 0;
//http请求回调函数,用于处理服务器端的返回消息
void http_request_done(struct evhttp_request *req, void *arg)
printf("send request ok...\\n");
size_t len = evbuffer_get_length(req->input_buffer);
unsigned char * str = evbuffer_pullup(req->input_buffer, len);
char buf[256] = 0 ;
memcpy(buf, str, len);
if (str == NULL)
printf("len = %d, str == NULL\\n", len);
else
printf("len = %d, str = %s\\n", len, buf);
event_base_loopbreak((struct event_base*)arg);
int main()
struct event_base* base;
struct evhttp_connection* conn;
struct evhttp_request* req;
#ifdef WIN32
init_win_socket();
#endif
base = event_base_new();
conn = evhttp_connection_new("127.0.0.1", 8081);
evhttp_connection_set_base(conn, base);
req = evhttp_request_new(http_request_done, base); //创建http请求对象
evhttp_add_header(req->output_headers, "Host", "localhost"); //填充http请求头内容
evhttp_make_request(conn, req, EVHTTP_REQ_GET, "/test"); //发送http请求
evhttp_connection_set_timeout(req->evcon, 600); //设置超时时间,超过这个时间还没收到服务端消息,则自动回调本地回调函数http_request_done
event_base_dispatch(base);
evhttp_connection_free(conn);
event_base_free(base);
printf("run over...\\n");
system("pause");
return 0;
以上是关于libevent evhttp多线程的主要内容,如果未能解决你的问题,请参考以下文章