You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
3.8 KiB

  1. 
  2. #include <iostream>
  3. #include <event2/http.h>
  4. #include<event2/event.h>
  5. #include <event2/listener.h>
  6. #include <event2/keyvalq_struct.h>
  7. #include <event2/buffer.h>
  8. #include <string.h>
  9. #ifndef _WIN32
  10. #include <signal.h>
  11. #include "test_http_server.h"
  12. #endif // !_WIN32
  13. using namespace std;
  14. #define WEBROOT "."
  15. #define DEFAULTINDEX "index.html"
  16. void http_cb(struct evhttp_request* request, void *arg) {
  17. cout << "http_cb" << endl;
  18. //1 获取浏览器请求信息
  19. //url
  20. const char* uri = evhttp_request_get_uri(request);
  21. cout << "uri:" << uri << endl;
  22. //获取请求类型Get Post
  23. string cmdtype;
  24. evhttp_cmd_type type = evhttp_request_get_command(request);
  25. switch (type)
  26. {
  27. case EVHTTP_REQ_GET:
  28. cout << "EVHTTP_REQ_GET" << endl;
  29. break;
  30. case EVHTTP_REQ_POST:
  31. break;
  32. case EVHTTP_REQ_HEAD:
  33. break;
  34. case EVHTTP_REQ_PUT:
  35. break;
  36. case EVHTTP_REQ_DELETE:
  37. break;
  38. case EVHTTP_REQ_OPTIONS:
  39. break;
  40. case EVHTTP_REQ_TRACE:
  41. break;
  42. case EVHTTP_REQ_CONNECT:
  43. break;
  44. case EVHTTP_REQ_PATCH:
  45. break;
  46. default:
  47. break;
  48. }
  49. //消息报头
  50. evkeyvalq *headers = evhttp_request_get_input_headers(request);
  51. cout << "========headers========\n" << endl;
  52. for (evkeyval *p = headers->tqh_first; p != NULL; p = p->next.tqe_next) {
  53. cout << p->key << ":" << p->value << endl;
  54. }
  55. //请求正文
  56. evbuffer*inbuf = evhttp_request_get_input_buffer(request);
  57. char buf[1024] = { 0 };
  58. cout << "=========Input data ===========" << endl;
  59. while (evbuffer_get_length(inbuf)) {
  60. int n = evbuffer_remove(inbuf, buf, sizeof(buf) - 1);
  61. if (n > 0) {
  62. buf[n] = '\0';
  63. cout << buf << endl;
  64. }
  65. }
  66. //2 回复浏览器
  67. //状态行 响应正文
  68. //消息报头
  69. evkeyvalq *outhead = evhttp_request_get_output_headers(request);
  70. //分析URI
  71. //设置根目录
  72. string filepath = WEBROOT;
  73. filepath += uri;
  74. if (strcmp(uri, "/") == 0) {
  75. filepath += DEFAULTINDEX;
  76. }
  77. //文件后缀
  78. int pos = filepath.rfind(".");
  79. string postfix = filepath.substr(pos+1,filepath.size() - (pos+1));
  80. if (postfix == "jpg" || postfix == "png" || postfix == "gif" || postfix == "ico") {
  81. string temp = "image/" + postfix;
  82. evhttp_add_header(outhead, "Content-Type", temp.c_str());
  83. }
  84. else if (postfix == "zip") {
  85. evhttp_add_header(outhead, "Content-Type", "application/zip");
  86. }
  87. else if (postfix == "html") {
  88. evhttp_add_header(outhead, "Content-Type", "text/html;charset=UTF8");
  89. }
  90. else if (postfix == "css") {
  91. evhttp_add_header(outhead, "Content-Type", "text/css");
  92. }
  93. FILE *fp = fopen(filepath.c_str(), "rb");
  94. if (!fp) {
  95. evhttp_send_reply(request, HTTP_NOTFOUND, "", 0);
  96. return;
  97. }
  98. evbuffer *outbuf = evhttp_request_get_output_buffer(request);
  99. for (;;) {
  100. int len = fread(buf, 1,sizeof(buf), fp);
  101. if (len <= 0)
  102. break;
  103. evbuffer_add(outbuf, buf, len);
  104. }
  105. fclose(fp);
  106. evhttp_send_reply(request, HTTP_OK, "", outbuf);
  107. }
  108. int main()
  109. {
  110. #ifdef _WIN32
  111. //初始化socket库
  112. WSADATA wsa;
  113. WSAStartup(MAKEWORD(2, 2), &wsa);
  114. #else
  115. if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { //忽略管道信号,发送数据给已关闭的socket,会飞掉!
  116. return 1;
  117. }
  118. #endif
  119. //创建libevent上下文
  120. event_base* base = event_base_new();
  121. if (base) {
  122. std::cout << "test server" << "\n";
  123. }
  124. //http 服务器
  125. //1.创建evhttp上下文
  126. evhttp *evh = evhttp_new(base);
  127. //2.绑定端口、IP
  128. if (evhttp_bind_socket(evh, "0.0.0.0", 8080) != 0) {
  129. cout << "绑定失败" << endl;
  130. }
  131. //3. 设定回调函数
  132. evhttp_set_gencb(evh, http_cb, 0);
  133. if (base)
  134. event_base_dispatch(base); //事件分发处理
  135. if (base)
  136. event_base_free(base);
  137. if (evh)
  138. evhttp_free(evh);
  139. #if _WIN32
  140. WSACleanup();
  141. #endif // _WIN32
  142. return 0;
  143. }