使用libevent2 实现 http_server
使用http实现libevent
linux http server 完整代码如下:
//LIBS += -levent qt工程pro 链接设置
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <event.h>
#include <evhttp.h>
void httpserver_handler(struct evhttp_request *req, void *arg)
{
const char *cmd_type;
struct evbuffer *buf = evbuffer_new();
if (buf == NULL)
{
printf("evbuffer_new error !\n");
return;
}
switch (evhttp_request_get_command(req))
{
case EVHTTP_REQ_GET: cmd_type = "GET"; break;
case EVHTTP_REQ_POST: cmd_type = "POST"; break;
case EVHTTP_REQ_HEAD: cmd_type = "HEAD"; break;
case EVHTTP_REQ_PUT: cmd_type = "PUT"; break;
case EVHTTP_REQ_DELETE: cmd_type = "DELETE"; break;
case EVHTTP_REQ_OPTIONS:cmd_type = "OPTIONS";break;
case EVHTTP_REQ_TRACE: cmd_type = "TRACE"; break;
case EVHTTP_REQ_CONNECT:cmd_type = "CONNECT";break;
case EVHTTP_REQ_PATCH: cmd_type = "PATCH"; break;
default: cmd_type = "unknown"; break;
}
printf("%s url=%s \n", cmd_type, evhttp_request_get_uri(req));
evbuffer_add_printf(buf,"<html>\n"
"<head>\n"
" <title>libevent http server </title>\n"
"</head>\n"
"<body>\n"
" <h1>libevent http server start success</h1>\n"
"</body>\n"
"</html>\n");
evhttp_send_reply(req, 200, "OK", buf);
}
int create_listener(int port, int backlog)
{
int ret;
int fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
printf("socket error !\n");
return -1;
}
int opt = 1;
ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, 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);
ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (ret < 0)
{
printf("bind error !\n");
return -1;
}
ret = listen(fd, backlog);
if (ret < 0)
{
printf("listen error !\n");
return -1;
}
int flags;
if ((flags = fcntl(fd, F_GETFL, 0)) < 0
|| fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
{
printf("fcntl error !\n");
return -1;
}
return fd;
}
int start_httpserver(int port)
{
int ret;
int fd = create_listener(port, 128);
if (fd < 0)
{
return -1;
printf("create_listener error !\n");
}
struct event_base *base = event_init();
if (base == NULL)
{
printf("event_init error !\n");
return -1;
}
struct evhttp *httpd = evhttp_new(base);
if (httpd == NULL)
{
printf("enhttp_new error !\n");
return -1;
}
ret = evhttp_accept_socket(httpd, fd);
if (ret != 0)
{
printf("evhttp_accept_socket error \n");
return -1;
}
evhttp_set_gencb(httpd, httpserver_handler, NULL);
printf("http server success started\n");
event_base_dispatch(base);
return 0;
}
int main(void)
{
start_httpserver(8080);
return 0;
}
基础环境:ubuntu:18.04
编译前安装依赖 :(我们使用libevent 库作为使用的http与网络开源库)
sudo apt-get install -y libevent-dev
编译命令:
g++ main.cpp -levent -o http_server
http_server 即是编译成功的http server了
运行:
./http_server
编译与运行示例图:
测试:
1、浏览器测试: 浏览器打开:http://127.0.0.1:8080 回车
效果:
2、通过curl命令命令行测试: curl http://127.0.0.1:8080 回车
curl 是一个http 客户端命令行软件,非常好用
没有的话需要安装: sudo apt-get install -y curl
部分代码说明:
如何实现一个http server
一个高性能网络开源库libevent
memcached 内存数据库的底层网络库是 libevent
O_NONBLOCK 把监听的socket 设置成了非阻塞的socket
为甚libevent 是事件驱动的呢
我们写代码的是往里面去注册事件 跟事件的处理回调函数
事件+回调函数 (libevent运行机制!!!!事件驱动)
event_init 初始化libevent
struct evhttp *httpd = evhttp_new(base);
新建一个 libevent 的事件
evhttp_accept_socket(httpd, fd)
把事件跟我们的监听socket 绑定
httpserver_handler 监听socket 的 回调函数
evhttp_set_gencb(httpd, httpserver_handler, NULL);
event_base_dispatch 是libevent的内部循环函数!!!
通过注册的回调函数 来执行我的代码
evhttp_request_get_uri 读取客户端的url
evhttp_send_reply 函数是把请求发回给客户端
这个代码一共三个函数
create_listener 就是创建监听socket
start_httpserver 初始化libevent ,以及注册了监听socket 的事件处理事件
httpserver_handler 监听socket 的 回调函数