一.依然要创建base上下文
event_base*base=event_base_new();
if(!base){
cout<<"event_base Failed !"<<endl;
return -1;
}
二.创建evhttp事件
evhttp*evh=evhttp_new(base);
if(!evh){
cout<<"evhttp_new Failed !"<<endl;
return -1;
}
三.绑定http服务器的套接字
使用函数 evhttp_bind_socket(evhttp*evh,const char *ip,uint16_t port);
第一个参数evh是上面创建的evhttp事件,第二个参数是要绑定的套接字的地址,第三个套接字是要绑定的套接字的端口号。
evhttp_bind_socket(evh,"**********",80);
四.绑定evhttp事件的回调函数(有链接时自动进入回调函数)
使用函数void evhttp_set_gencb(struct evhttp *http, void (*cb)(struct evhttp_request *, void *), void *arg);
第一个参数依然是我们创建的evh,第二个参数是http服务器有链接进入时进入的回调函数,第三个参数是回调函数的参数。
五.回调函数
void Http_CB(evhttp_request*request,void *arg);
这是evhttp的回调函数,当链接进入时会自动进入,之后所有的操作都基于这个request完成!由于http是请求回应式链接,所以一次次的请求都会进入此回调函数。并生成对应的request请求。
如下便是实现一个轻量http的实列。
#include<iostream>
#include <unistd.h>
#include<sys/fcntl.h>
#include<event2/keyvalq_struct.h>
#include<arpa/inet.h>
#include<event2/buffer.h>
#include<event2/event.h>
#include<event2/http.h>
using namespace std;
void Http_CB(evhttp_request*request,void *arg){
evkeyvalq *outheader=evhttp_request_get_output_headers(request);//获取输出协议头
evbuffer* outbuf=evhttp_request_get_output_buffer(request); //获取输出缓存
evhttp_add_header(outheader,"Content-Type","text/html"); //增加http协议头
int fp=open("./index.html",O_RDONLY|O_NONBLOCK,0); //打开文件描述符
if(!fp){
cout<<"open fp !"<<endl;
return ;
}
int len=lseek(fp,0,SEEK_END); //获取文件大小
evbuffer_add_file(outbuf,fp,0,len);//将文件描述符添加至输出缓存 linux下优先使用sendfile技术
evhttp_send_reply(request,HTTP_OK,"ok",outbuf);//回复浏览器
}
int main(){
event_base*base=event_base_new();
if(!base){
cout<<"event_base Failed !"<<endl;
return -1;
}
evhttp*evh=evhttp_new(base);
if(!evh){
cout<<"evhttp_new Failed !"<<endl;
return -1;
}
evhttp_bind_socket(evh,"192.168.84.128",8080);
evhttp_set_gencb(evh,Http_CB,base);
event_base_dispatch(base);//base分发
if(evh)evhttp_free(evh);
if(base)event_base_free(base);
}