基于Libevent的HTTP Server
libevent源码分析

libevent源码分析这两天没事,看了⼀下Memcached和libevent的源码,做个⼩总结。
1、⼊门1.1、概述Libevent是⼀个⽤于开发可扩展性⽹络服务器的基于事件驱动(event-driven)模型的⽹络库。
Libevent有⼏个显著的亮点:(1)事件驱动(event-driven),⾼性能;(2)轻量级,专注于⽹络,不如 ACE 那么臃肿庞⼤;(3)源代码相当精炼、易读;(4)跨平台,⽀持 Windows、Linux、*BSD和 Mac Os;(5)⽀持多种 I/O多路复⽤技术, epoll、poll、dev/poll、select 和kqueue 等;(6)⽀持 I/O,定时器和信号等事件;(7)注册事件优先级;Libevent 已经被⼴泛的应⽤,作为底层的⽹络库;⽐如 memcached、 Vomi t、 Nylon、 Netchat等等。
1.2、⼀个简单⽰例代码1int lasttime;23static void4 timeout_cb(int fd, short event, void *arg)5 {6struct timeval tv;7struct event *timeout = arg;8int newtime = time(NULL);910//printf("%s: called at %d: %d\n", __func__, newtime,11 printf("%s: called at %d: %d\n", "timeout_cb", newtime,12 newtime - lasttime);13 lasttime = newtime;1415 evutil_timerclear(&tv);16 _sec = 2;17//重新注册event18 event_add(timeout, &tv);19 }2021int22 main (int argc, char **argv)23 {24struct event timeout;25struct timeval tv;2627/* Initalize the event library */28//初始化event环境29 event_init();3031/* Initalize one event */32//设置事件33 evtimer_set(&timeout, timeout_cb, &timeout);3435 evutil_timerclear(&tv);36 _sec = 2;37//注册事件38 event_add(&timeout, &tv);3940 lasttime = time(NULL);4143 event_dispatch();4445return (0);46 }这是⼀个简单的基于libevent的定时器程序,运⾏结果:⽤libevent编程⾮常简单,只需要调⽤event_init初始化环境,然后调⽤event_add注册相应的事件,接着调⽤event_dispatch等待并处理相应的事件即可。
libevent ipv6用法

Libevent是一个开源的事件通知库,用于在网络编程中处理事件驱动的程序。
它是一个轻量级的、高性能的库,广泛用于服务器软件的开发中。
在IPv6的网络环境下,Libevent同样可以发挥其强大的功能,本文将探讨Libevent在IPv6环境下的使用方法。
一、Libevent简介Libevent是一个基于事件驱动的网络编程库,支持跨评台(包括Unix/Linux、Windows等)和多种网络协议。
它提供了事件处理、定时器管理、信号处理等功能,可以帮助开发者编写高效的服务器程序。
Libevent使用简单,性能优异,深受广大开发者的喜爱。
二、IPv6概述IPv6是下一代的互联网协议,它是IPv4的后继者,为互联网用户提供了更多的IP位置区域空间,解决了IPv4位置区域短缺的问题。
IPv6的位置区域长度为128位,相较于IPv4的32位位置区域,拥有更大的位置区域空间和更好的路由选择,同时支持IPsec等安全性功能。
三、Libevent在IPv6环境中的使用在IPv6的网络环境下,Libevent同样可以发挥其强大的功能。
在使用Libevent进行网络编程时,我们需要注意以下几点:1. IPv6位置区域族在Libevent中,IPv6位置区域族使用的是AF_INET6。
当创建套接字时,需要指定位置区域族为AF_INET6,以便能够支持IPv6的通信。
示例代码如下:```struct sockaddr_in6 sin;memset(sin, 0, sizeof(sin));sin.sin6_family = AF_INET6;sin.sin6_port = htons(8080);sin.sin6_addr = in6addr_any;```2. 位置区域转换在IPv6环境下,我们可能需要将IPv6位置区域(如文本格式的IPv6位置区域)转换为网络字节序,或者将网络字节序的IPv6位置区域转换为文本格式。
1+x云运维模拟题及答案

1+x云运维模拟题及答案1、下面关于ARP工作原理的描述,不正确的是A、是通过IP地址查询对应的MAC地址B、 ARP缓存中的数据是动态更新的C、 ARP请求报文可以跨网段传输D、 ARPA是通过AMC查询对应的IP地址答案:C2、下列哪些选项属于列存储数据库A、Neo4JB、RedisC、HbaseD、MongoDB答案:C3、管理信息库(MIB)中的管理数据如果是表数据,要使用snmp get操作对表中的某行某列数据进行读取,get操作的对象识别是下面哪种格式?A、表对象oidB、列对象oidC、列对象od + 列索引D、列索引答案:C4、jobs命令是什么命令A、查看处理后台的任务列表B、查看定时任务C、查看运行的进程D、执行任务答案:A5、哪种snmp操作可以实现对被管理设备数据的修改?A、 SetB、 TrapC、 GetD、 GetBulk答案:A6、如果要退出命令行模式进入菜单驱动文本控制台,可在命令行模式下输入A、exitB、escC、xsconsoleD、quit答案:C7、多媒体网络(三网合一)设计时,考虑的主要问题是:A、可靠性B、安全问题C、带宽问题D、负载均衡答案:C8、如果要退出命令行模式进入菜单驱动文本控制台,可在命令行模式下输入A、 exitB、 escC、 xsconsoleD、 quit答案:C9、system_u:object_r:admin_home_t:s0中system_u表示为A、角色B、 SELinux中最重要的信息C、类型D、用户答案:D10、Redis的RDB文件检查工具是什么A、 redis-check-dumpB、 redis-benchmarkC、 redis-check-aofD、 redis-cli答案:A11、下面关于ARP工作原理的描述,不正确的是A、是通过IP地址查询对应的MAC地址B、 ARP缓存中的数据是动态更新的C、 ARP请求报文可以跨网段传输D、 ARPA是通过AMC查询对应的IP地址答案:C12、下列选项中哪一个是Nginx的配置文件A、 fB、 nginx.confC、 systemconfD、 nginx.con答案:B13、 Memcached什么命令用于向已存在key的value后面追加数据A、addB、replaceC、setD、append答案:D14、解诀网络问题的过程中哪个步骤需要询问用户,以便了解解决问题所需的信息?A、收集信息B、界定故障现象C、列举可能导致故障的原因D、排查原因答案:C15、哪种snmp操作可以实现对被管理设备数据的修改?A、 SetB、 TrapC、 GetD、 GetBulk答案:A16、Linux操作系统中添加用户的命令A、 useraddB、 adduserC、 usD、 addus答案:A17、下列哪些选项属于图像数据库A、Neo4JB、RedisC、HbaseD、MongoDB答案:A18、 Nginx配置文件中每一条指令用什么符号结束A、#B、$C、:D、;答案:D19、下面关于ARP工作原理的描述,不正确的是A、是通过IP地址查询对应的MAC地址B、 ARP缓存中的数据是动态更新的C、 ARP请求报文可以跨网段传输D、 ARPA是通过AMC查询对应的IP地址答案:C20、DNS全局负载均衡能够实现哪种粒度的负载均衡A、每个TCP连接B、每个公网IPC、每个HTTP会话D、每个本地DNS覆盖的区域答案:D21、DNS全局负载均衡能够实现哪种粒度的负载均衡A、每个TCP连接B、每个公网IPC、每个HTTP会话D、每个本地DNS覆盖的区域答案:D22、管理信息库(MIB)中的管理对象是使用哪种方式组织的?A、树形B、链表C、图D、数组答案:A23、需求分析是作为一个网络设计时所必须的,它可以实现:A、了解宏观政策B、提高网络性能C、建设有针对性的网络D、了解新技术答案:C24、一位计算机操作人员注意到他的全部磁盘空间马上就要用完了。
libevent2http客户端示例

libevent2http客户端示例2013.09Libevent 的文档非常少, 而且示例也很奇缺, 在 Google 里一搜, 还真找不到一两个. 这里贴一个最简单的利用 Libevent 2 HTTP 库, 作为客户端向服务器发起请求的例子.#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <unistd.h>#include <evhttp.h>#include <event2/event.h>#include <event2/http.h>#include <event2/bufferevent.h>void http_request_done(struct evhttp_request *req, void *arg){char buf[1024];int s = evbuffer_remove(req->input_buffer, &buf, sizeof(buf) - 1);buf[s] = '\0';printf("%s", buf);// terminate event_base_dispatch()event_base_loopbreak((struct event_base *)arg);}int main(int argc, char **argv){struct event_base *base;struct evhttp_connection *conn;struct evhttp_request *req;base = event_base_new();conn = evhttp_connection_base_new(base, NULL, "127.0.0.1", 8080);req = evhttp_request_new(http_request_done, base);evhttp_add_header(req->output_headers, "Host", "localhost");//evhttp_add_header(req->output_headers, "Connection", "close");evhttp_make_request(conn, req, EVHTTP_REQ_GET, "/index.php?id=1");evhttp_connection_set_timeout(req->evcon, 600);event_base_dispatch(base);return 0;}Related posts:1. 150行C代码的comet服务器2. Libevent HTTP 内存泄露3. 让libevent HTTP服务器立即知道客户端的断开4. 基于列的数据库5. 使用 jemalloc 编译过程出错的问题。
基于区块链的健康链系统设计与实现

收稿日期:2020年6月13日,修回日期:2020年7月26日基金项目:科技部重点研发项目“现代服务可信交易理论与技术研究(面向服务可信交易的新型区块链分布式架构)”(编号:2018YFB1402701)资助。
作者简介:雷志伟,男,工程师,研究方向:区块链、游戏引擎开发。
李加福,男,高级工程师,研究方向:区块链、图像处理。
张桂刚,男,博士,副研究员,研究方向:区块链和人工智能。
赵旭,男,硕士,研究方向:区块链、机器翻译。
张勇,男,博士,副研究员,研究方向:数据管理、云存储、海量信息处理。
邢春晓,男,博士,研究员,研究方向:数据库和数据仓库,大数据和知识工程、人工智能,软件工程,区块链技术,智慧城市、智慧医疗、数字图书馆和电子政务关键技术等。
∗1引言在抗击新冠肺炎疫情初期,各地各部门企业纷纷贡献己力,自主开发疫情防控信息系统。
一方面能加强政府部门的管理,另一方面简化现实中人力物力消耗[1]。
在人员进出公共场所的跟踪管理方面,相应有应用于广西地区的“扫码抗疫情”、云南地区的“云南抗疫情”等。
它们都是基于微信小程基于区块链的健康链系统设计与实现雷志伟1李加福1张桂刚2赵旭3张勇3邢春晓3(1.清华大学行业可信区块链应用技术联合研究中心北京100084)(2.中国科学院自动化研究所北京100190)(3.清华大学信息国家研究中心,计算机系,互联网产业研究院北京100084)摘要新冠疫情在全球范围肆虐,公共场合中的体温测量和行踪登记是控制疫情蔓延的关键手段,目前的信息记录主要依赖人工纸张录入的方式。
纸张录入的方式不仅效率低下,而且还面临着易损易丢失的存档风险,同时难以对过往人员与行踪进行快速筛查。
该系统基于微信小程序的开发框架,实现了扫码快速注册以及信息登记的功能,同时基于区块链技术来实现底层数据存储和优化,保证数据的不可篡改和快速溯源,最后通过Nginx 服务器进行数据通信。
关键词比特币;区块链;微信小程序;健康链;Nginx中图分类号TP393DOI :10.3969/j.issn.1672-9722.2020.12.016Design and Implementation of Health Chain System Based onBlockchainLEI Zhiwei 1LI Jiafu 1ZHANG Guigang 2ZHAO Xu 3ZHANG Yong 3XING Chunxiao 3(1.Joint Research Center for Industry Trust Blockchain Application Technology ,Tsinghua University ,Beijing100084)(2.Institute of Automation ,Chinese Academy of Sciences ,Beijing100190)(3.Institute of Internet Industry ,Department of Computer Science and Technology ,Beijing National Research Center forInformation Science and Technology (BNRist ),Tsinghua University ,Beijing100084)AbstractDuring the COVID-19,temperature measurement and whereabouts registration in public are the key to control thespread of the virus.Current information recording mainly relies on manual paper entry which is not only inefficient ,but also fragileand easy to lose ,and it is difficult to retrieve the past data.This system is based on the Wechat Mini Program ,the information re⁃cording is implemented easily by scanning QR codes to improve efficiency.Moreover ,managing the storage and optimization of the underlying data based on blockchain technology ensure the data security and fast traceability.Finally ,the data communication is performed through the Nginx server.Key Words Bitcoin ,blockchain ,Wechat mini program ,health chain ,NginxClass NumberTP3932020年第12期计算机与数字工程序开发,其功能和使用方式大抵相同,群众以个人身份注册,另一个则是公共场所的工作人员以公共场所的身份进入系统并生成二维码进行张贴,进出人员手动扫码实现数据上传,从而减免了手工登记流程。
libevent和基于libevent的网络编程

libevent和基于libevent的⽹络编程1 libevent介绍和安装介绍libevent是⼀个轻量级的基于事件驱动的⾼性能的开源⽹络库,并且⽀持多个平台,对多个平台的I/O复⽤技术进⾏了封装,当我们编译库的代码时,编译的脚本将会根据OS⽀持的处理事件机制,来编译相应的代码,从⽽在libevent接⼝上保持⼀致。
在当前的服务器上,⾯对的主要问题就是要能处理⼤量的连接。
⽽通过libevent这个⽹络库,我们就可以调⽤它的API来很好的解决上⾯的问题。
⾸先,可以来回顾⼀下,对这个问题的传统解决⽅法。
问题:如何处理多个客户端连接解决⽅案1:I/O复⽤技术这⼏种⽅式都是同步I/O,即当读写事件就绪,他们⾃⼰需要负责进⾏读写,这个读写过程是阻塞的,⽽异步I/O则不需要⾃⼰负责读写,只需要通知负责读写的程序就可以了。
循环假设当前我服务器有多个⽹络连接需要看管,那么我就循环遍历打开的⽹络连接的列表,来判断是否有要读取的数据。
这种⽅法的缺点很明显,那就是 1.速度缓慢(必须遍历所有的⽹络连接) 2.效率低(处理⼀个连接时可能发⽣阻塞,妨碍其他⽹络连接的检查和处理)select⽅式select对应于内核中的sys_select调⽤,sys_select⾸先将第⼆三四个参数指向的fd_set拷贝到内核,然后对每个被SET的描述符调⽤进⾏poll,并记录在临时结果中(fdset),如果有事件发⽣,select会将临时结果写到⽤户空间并返回;当轮询⼀遍后没有任何事件发⽣时,如果指定了超时时间,则select会睡眠到超时,睡眠结束后再进⾏⼀次轮询,并将临时结果写到⽤户空间,然后返回。
select返回后,需要逐⼀检查关注的描述符是否被SET(事件是否发⽣)。
(select⽀持的⽂件描述符数量太⼩了,默认是1024)。
poll⽅式poll与select不同,通过⼀个pollfd数组向内核传递需要关注的事件,故没有描述符个数的限制,pollfd中的events字段和revents分别⽤于标⽰关注的事件和发⽣的事件,故pollfd数组只需要被初始化⼀次。
libhv用法范文

libhv用法范文libhv是基于事件驱动的高性能网络编程框架,主要用于快速开发可扩展的网络应用程序。
libhv提供了一些核心组件和工具,如事件驱动的网络库、HTTP服务器、协程调度器等,方便开发者构建高性能、高可用性的网络应用程序。
下面将重点介绍libhv的用法,包括网络库的使用、HTTP服务器的开发以及协程的编程。
一、网络库的使用1.创建网络服务使用hvlisten函数创建一个TCP服务监听套接字,示例代码如下:```hv::EventLoopPtr loop(new hv::EventLoop();hv::TcpServerPtr tcp(new hv::TcpServer(loop));tcp->bind("0.0.0.0", 8080);tcp->onMessage([](const hv::TcpConnPtr& conn, const char* buf, int len)conn->send(buf, len);});tcp->start(;```2.处理网络事件使用循环调用hvevent函数处理网络事件,示例代码如下:```hv::EventLoop loop;while (true)loop.hvevent(1000); // 处理网络事件,超时时间1秒// do other things```二、HTTP服务器的开发1.创建HTTP服务器```HttpResponse resp;resp.setBody("Hello, World!");resp.setContentType("text/plain");ctx->sendResponse(resp);});```2.处理HTTP请求使用onHttpRequest函数设置请求处理函数,示例代码如下:```HttpRequest& req = ctx->request(;HttpResponse resp;resp.setBody("Hello, " + req.getPath();resp.setContentType("text/plain");ctx->sendResponse(resp);});```三、协程的编程1.创建协程使用co创建一个协程,示例代码如下:```co([// do something});```2.协程同步通信使用cocall可以在协程之间同步调用,示例代码如下:```std::string result = cocall([// do somethingreturn "result";});```3.协程并发编程使用co_parallel函数可以在多个协程之间并发执行,示例代码如下:```co_parallel([co([// do something});co([// do something});});```总结:libhv是一个非常强大的网络编程框架,可以帮助开发者快速构建高性能的网络应用程序。
http-server学习使用总结

http-server学习使⽤总结学习时查了到的资料⽤于备注保存http-server 是⼀个简单的零配置命令⾏HTTP服务器, 基于 nodeJs。
⽤于测试,本地开发,学习。
http-server安装⽹站建议全局安装 npm install –g1,在站点⽬录下开启命令⾏输⼊http-server start在全局访问需要设置路径http-server [path] [options]默认路径: ./public如果不存在或不是想要访问的路径,可通过设置其他访问路径2,在package.json设置"scripts": {"start": "http-server -a 0.0.0.0 -p 8000",}3,浏览器访问例如或注:在当前⽂件夹内执⾏运⾏命令,则默认的根⽬录为当前⽂件夹参数:-p 端⼝号 (默认 8080)-a IP 地址 (默认 0.0.0.0)-d 显⽰⽬录列表 (默认 'True')-i 显⽰ autoIndex (默认 'True')-e or --ext 如果没有提供默认的⽂件扩展名(默认 'html')-s or --silent 禁⽌⽇志信息输出--cors 启⽤ CORS via the Access-Control-Allow-Origin header-o 在开始服务后打开浏览器- c设置缓存时间(以秒为单位)cache - control头信息,例如c10 10秒钟(默认为“3600”)。
禁⽤缓存,请使⽤。
- u和- utc⽇志消息中使⽤utc时间格式。
- p或者——代理代理所有请求,不能进⾏本地解析给定的url。
如。
:- p - s或者——ssl启⽤https。
- c或- cert路径ssl证书⽂件(默认值:cert.pem)。
- k或——关键路径ssl密钥⽂件(默认值:key.pem)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于Libevent的HTTP Server简单的Http Server使用Libevent内置的http相关接口,可以很容易的构建一个Http Server,一个简单的Http Server如下:#include <event2/event.h>#include <event2/buffer.h>#include <event2/http.h>#include <Winsock2.h>#include <stdlib.h>#include <stdio.h>int init_win_socket(){WSADATA wsaData;if(WSAStartup(MAKEWORD(2,2) , &wsaData) != 0){return -1;}return0;}void generic_handler(struct evhttp_request *req, void *arg){struct evbuffer *buf = evbuffer_new();if(!buf){puts("failed to create response buffer \n");return;}evbuffer_add_printf(buf, "Server Responsed. Requested: %s\n", evhttp_request_get_uri(req));evhttp_send_reply(req, HTTP_OK, "OK", buf);evbuffer_free(buf);}int main(int argc, char* argv[]){#ifdef WIN32init_win_socket();#endifshort http_port = 8081;char *http_addr = "127.0.0.1";struct event_base * base = event_base_new();struct evhttp * http_server = evhttp_new(base);if(!http_server){return -1;}int ret = evhttp_bind_socket(http_server,http_addr,http_port);if(ret!=0){return -1;}evhttp_set_gencb(http_server, generic_handler, NULL);printf("http server start OK! \n");event_base_dispatch(base);evhttp_free(http_server);WSACleanup();return0;}通过Libevent的接口构建一个Http Server的过程如下:(1)初始化:在event_base上新建一个evhttp,将这个evhttp绑定到监听的IP和端口号。
(2)设置Http回调函数:使用evhttp_set_gencb设置Http Server的处理请求的回调函数。
(3)启动Http Server:等待请求进入事件循环。
在Http Server中使用定时器提供更新服务#include <event2/event.h>#include <event2/buffer.h>#include <event2/http.h>#include <sys/stat.h>#include <Winsock2.h>#include <assert.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#define DEFAULT_FILE "F:\\Libevent\\LibeventTest\\Debug\\sample.txt"char *filedata;time_t lasttime = 0;char filename[80];int counter = 0;struct event *loadfile_event;struct timeval tv;void read_file(){unsigned long size = 0;char *data;struct stat buf;if(stat(filename,&buf)<0){printf("Read file error! \n");return;}if (buf.st_mtime > lasttime){if (counter++)fprintf(stderr,"Reloading file: %s",filename);elsefprintf(stderr,"Loading file: %s",filename);FILE *f = fopen(filename, "rb");if (f == NULL){fprintf(stderr,"Couldn't open file\n");return;}size = buf.st_size;filedata = (char *)malloc(size+1);memset(filedata,0,size+1);fread(filedata, sizeof(char), size, f);fclose(f);fprintf(stderr," (%d bytes)\n",size);lasttime = buf.st_mtime;}}void read_file_timer_cb(evutil_socket_t listener, short event, void *arg){if (!evtimer_pending(loadfile_event, NULL)){event_del(loadfile_event);evtimer_add(loadfile_event, &tv);}read_file();}void load_file(struct event_base * base){_sec = 5;_usec = 0;//loadfile_event = malloc(sizeof(struct event));loadfile_event = evtimer_new(base,read_file_timer_cb,NULL);//evtimer_set(loadfile_event,load_file,loadfile_event);evtimer_add(loadfile_event,&tv);}void generic_handler(struct evhttp_request *req, void *arg){struct evbuffer *buf = evbuffer_new();if(!buf){puts("failed to create response buffer \n");return;}evbuffer_add_printf(buf,"%s",filedata);evhttp_send_reply(req, HTTP_OK, "OK", buf);evbuffer_free(buf);}int init_win_socket(){WSADATA wsaData;if(WSAStartup(MAKEWORD(2,2) , &wsaData) != 0){return -1;}return0;}int main(int argc, char* argv[]){#ifdef WIN32init_win_socket();#endifshort http_port = 8081;char *http_addr = "127.0.0.1";if (argc > 1){strcpy(filename,argv[1]);printf("Using %s\n",filename);}else{strcpy(filename,DEFAULT_FILE);}struct event_base * base = event_base_new();struct evhttp * http_server = evhttp_new(base);if(!http_server){return -1;}int ret = evhttp_bind_socket(http_server,http_addr,http_port);if(ret!=0){return -1;}evhttp_set_gencb(http_server, generic_handler, NULL);read_file();load_file(base);printf("http server start OK! \n");event_base_dispatch(base);evhttp_free(http_server);WSACleanup();return0;}在这个Http Server中提供了一个每5秒触发一次的定时器,读取一个文件,如果这个文件被更新过,则读取更新后的内容。
当访问这个Http Server时,提供这个文件中最新的内容。
多线程的Http Server在上面的Http Server中,处理Http请求的回调函数generic_handler和定时器读取文件的回调函数read_file_timer_cb都在同一个event_base的dispatch中,并且都在同一个进程中,使用多线程可以改善程序的性能,下面是一个来自网络的多线程Http Server:#include <event.h>#include <evhttp.h>#include <pthread.h>#include <errno.h>#include <string.h>#include <fcntl.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.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);int httpserver_bindsocket(int port, int backlog) {int r;int nfd;nfd = socket(AF_INET, SOCK_STREAM, 0);if (nfd < 0) return -1;int one = 1;r = setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int));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);r = bind(nfd, (struct sockaddr*)&addr, sizeof(addr));if (r < 0) return -1;r = listen(nfd, backlog);if (r < 0) return -1;int flags;if ((flags = fcntl(nfd, F_GETFL, 0)) < 0|| fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) return -1;return nfd;}int httpserver_start(int port, int nthreads, int backlog) {int r, i;int 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;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);}}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(80, 10, 10240);}上面的代码基于Libevent 1.X版本的,不过很容易很看懂:在一个监听socket上创建了多个event_base实例和evhttp实例,在不同的线程中调度不同的event_base,继而可以在不同的线程中处理http请求。