c_http_server/main.cpp

160 lines
3.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <event2/event.h>
#include <event2/listener.h>
#include <event2/http.h>
#include <event2/keyvalq_struct.h>
#include <event2/buffer.h>
#include <string.h>
#ifndef _WIN32
#include <signal.h>
#endif
#include <iostream>
#include <string>
using namespace std;
#define WEBROOT "."
#define DEFAULTINDEX "index.html"
void http_cb(struct evhttp_request *request, void *arg)
{
cout << "http_cb" << endl;
//1 获取浏览器的请求信息
//uri
const char *uri = evhttp_request_get_uri(request);
cout << "uri:" << uri << endl;
//请求类型 GET POST
string cmdtype;
switch (evhttp_request_get_command(request)) {
case EVHTTP_REQ_GET:
cmdtype = "GET";
break;
case EVHTTP_REQ_POST:
cmdtype = "POST";
break;
}
cout << "cmdtype:" << cmdtype << endl;
// 消息报头
evkeyvalq *headers = evhttp_request_get_input_headers(request);
cout << "====== headers ======" << endl;
for (evkeyval *p = headers->tqh_first; p != NULL; p = p->next.tqe_next) {
cout << p->key << ":" << p->value << endl;
}
// 请求正文 (GET为空POST有表单信息 )
evbuffer *inbuf = evhttp_request_get_input_buffer(request);
char buf[1024] = { 0 };
cout << "======= Input data ======" << endl;
while (evbuffer_get_length(inbuf)) {
int n = evbuffer_remove(inbuf, buf, sizeof(buf) - 1);
if (n > 0)
{
buf[n] = '\0';
cout << buf << endl;
}
}
//2 回复浏览器
//状态行 消息报头 响应正文 HTTP_NOTFOUND HTTP_INTERNAL
string filepath = WEBROOT;
filepath += uri;
if (strcmp(uri, "/") == 0)
{
//默认加入首页文件
filepath += DEFAULTINDEX;
}
//消息报头
evkeyvalq *outhead = evhttp_request_get_output_headers(request);
// 要支持 图片 js css 下载zip文件
// 获取文件的后缀
// ./index.html
int pos = filepath.rfind('.');
string postfix = filepath.substr(pos + 1, filepath.size() - (pos + 1));
if (postfix == "jpg" || postfix == "gif" || postfix == "png")
{
string tmp = "image/" + postfix;
evhttp_add_header(outhead, "Content-Type", tmp.c_str());
}
else if (postfix == "zip")
{
evhttp_add_header(outhead, "Content-Type", "application/zip");
}
else if (postfix == "html")
{
evhttp_add_header(outhead, "Content-Type", "text/html;charset=UTF8");
//evhttp_add_header(outhead, "Content-Type", "text/html");
}
else if (postfix == "css")
{
evhttp_add_header(outhead, "Content-Type", "text/css");
}
//读取html文件返回正文
if(filepath.find_first_of("?")){
}
std::cout<<filepath.find_first_of("?")<<std::endl;
FILE *fp = fopen(filepath.c_str(), "rb");
if (!fp)
{
evhttp_send_reply(request, HTTP_NOTFOUND, "", 0);
return;
}
evbuffer *outbuf = evhttp_request_get_output_buffer(request);
for (;;)
{
int len = fread(buf, 1, sizeof(buf), fp);
if (len <= 0)break;
evbuffer_add(outbuf, buf, len);
}
fclose(fp);
evhttp_send_reply(request, HTTP_OK, "", outbuf);
}
int main(int argc,char *argv[])
{
#ifdef _WIN32
//初始化socket库
WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);
#else
//忽略管道信号发送数据给已关闭的socket
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
return 1;
#endif
std::cout << "test server!\n";
//创建libevent的上下文
event_base * base = event_base_new();
if (base)
{
cout << "event_base_new success!" << endl;
}
// http 服务器
//1 创建evhttp上下文
evhttp *evh = evhttp_new(base);
//2 绑定端口和IP
if (evhttp_bind_socket(evh, "0.0.0.0", 8080) != 0)
{
cout << "evhttp_bind_socket failed!" << endl;
}
//3 设定回调函数
evhttp_set_gencb(evh, http_cb, 0);
//事件分发处理
if(base)
event_base_dispatch(base);
if(base)
event_base_free(base);
if(evh)
evhttp_free(evh);
return 0;
}