libevent学习一:编译以及测试使用(windows版本)

  1. https://blog.****.net/u014088524/article/details/87303676
  2.  
  3.  
  4.  
  5. 下载地址:http://libevent.org/ ,下载版本:libevent-2.0.22-stable.tar.gz
  6. 解压, 目录为...\libevent-2.0.22-stable(自己的目录)
  7. 修改以下三个文件,添加宏定义:

    在以下3个文件开头添加“#define _WIN32_WINNT 0x0500”

    libevent-2.0.21-stable\event_iocp.c

    libevent-2.0.21-stable\evthread_win32.c

    libevent-2.0.21-stable\listener.c

  8. 打开VS2015命令工具,切换到解压后的libevent目录,然后执行nmake /f Makefile.nmake命令进行编译,命令如下图所示,

           先输入cd/d D:\aa_zhj\a_work\projects\libevent\libevent-2.0.22-stable切换目录,然后输入nmake /f Makefile.nmake进行编译。

    

libevent学习一:编译以及测试使用(windows版本)

 

编译成功后再libevent-2.0.22-stable目录下生成三个lib文件:

libevent.lib、libevent_core.lib、libevent_extras.lib

 

5.VS2015下使用lib

新建一个VC++控制台项目:

环境配置:

项目下建一个Lib目录,将上面三个lib文件copy到该目录下。

新建一个Include目录,将libevent-2.0.21-stable\include文件夹下的所有内容和WIN32-Code文件夹下的所有内容拷贝到新建的include目录下,两个event2目录下的文件可合并在一起。

6.项目属性设置

VC++目录:

包含目录,添加上面的Include目录;

库目录,添加上面的Lib目录;

libevent学习一:编译以及测试使用(windows版本)

libevent学习一:编译以及测试使用(windows版本)

 

 

C/C++:

代码生成-->运行库:多线程调试 (/MTd)(Debug下),多线程 (/MT)(Release下)

连接器:

输入:ws2_32.lib;wsock32.lib;libevent.lib;libevent_core.lib;libevent_extras.lib;

ws2_32.lib;wsock32.lib;是用来编译Windows网络相关的程序库。

高级-->编译为:编译为C++代码(/TP),(因为我的工程用到C++的函数所以配置这个)

网上有人推荐配置成TC的也可以,自己根据项目需要

 

 

配置忽略项,可以不配置

输入\忽略特定默认库 libc.lib;msvcrt.lib;libcd.lib;libcmtd.lib;msvcrtd.lib;%(IgnoreSpecificDefaultLibraries)

 

7. 生成lib后,不带调试信息,无法单步进函数里,所以要修改脚本:Makefile.nmake第二行

CFLAGS=$(CFLAGS) /Od /W3 /wd4996 /nologo /Zi

 

到此为止项目配置好了,我们来写相关的demo代码

 
  1. #include <stdio.h>

  2. #include <time.h>

  3. #include <io.h>

  4. #include <process.h>

  5. #include <WinSock2.h>

  6. #pragma comment(lib,"ws2_32.lib")

  7.  
  8. #include <event2/bufferevent.h>

  9. #include <event2/buffer.h>

  10. #include <event2/listener.h>

  11. #include <event2/util.h>

  12. #include <event2/event.h>

  13.  
  14. #pragma warning(disable:4996)

  15.  
  16. #define MAX_LINE 256

  17.  
  18. void read_cb(struct bufferevent *bev, void *arg) {

  19. struct evbuffer *buf = (struct evbuffer *)arg;

  20. char line[MAX_LINE + 1];

  21. int n;

  22. evutil_socket_t fd = bufferevent_getfd(bev);

  23. while (n = bufferevent_read(bev, line, MAX_LINE), n > 0) {

  24. line[n] = '\0';

  25.  
  26. //将读取到的内容放进缓冲区

  27. evbuffer_add(buf, line, n);

  28.  
  29. //搜索匹配缓冲区中是否有==,==号来分隔每次客户端的请求

  30. const char *x = "==";

  31. struct evbuffer_ptr ptr = evbuffer_search(buf, x, strlen(x), 0);

  32. if (ptr.pos != -1) {

  33. bufferevent_write_buffer(bev, buf); //使用buffer的方式输出结果

  34. }

  35. }

  36. }

  37. void write_cb(struct bufferevent *bev, void *arg) {}

  38. void error_cb(struct bufferevent *bev, short event, void *arg) {

  39. evutil_socket_t fd = bufferevent_getfd(bev);

  40. printf("fd = %u, ", fd);

  41. if (event & BEV_EVENT_TIMEOUT) {

  42. printf("Timed out\n");

  43. }

  44. else if (event & BEV_EVENT_EOF) {

  45. printf("connection closed\n");

  46. }

  47. else if (event & BEV_EVENT_ERROR) {

  48. printf("some other error\n");

  49. }

  50. //清空缓冲区

  51. struct evbuffer *buf = (struct evbuffer *)arg;

  52. evbuffer_free(buf);

  53. bufferevent_free(bev);

  54. }

  55.  
  56. //回调函数,用于监听连接进来的客户端socket

  57. void do_accept(evutil_socket_t fd, short event, void *arg) {

  58. int client_socketfd;//客户端套接字

  59. struct sockaddr_in client_addr; //客户端网络地址结构体

  60. int in_size = sizeof(struct sockaddr_in);

  61. //客户端socket

  62. client_socketfd = accept(fd, (struct sockaddr *) &client_addr, &in_size); //等待接受请求,这边是阻塞式的

  63. if (client_socketfd < 0) {

  64. puts("accpet error");

  65. exit(1);

  66. }

  67.  
  68. //类型转换

  69. struct event_base *base_ev = (struct event_base *) arg;

  70.  
  71. //socket发送欢迎信息

  72. char * msg = "Welcome to My socket";

  73. int size = send(client_socketfd, msg, strlen(msg), 0);

  74.  
  75. //创建一个事件,这个事件主要用于监听和读取客户端传递过来的数据

  76. //持久类型,并且将base_ev传递到do_read回调函数中去

  77. //struct event *ev;

  78. //ev = event_new(base_ev, client_socketfd, EV_TIMEOUT|EV_READ|EV_PERSIST, do_read, base_ev);

  79. //event_add(ev, NULL);

  80.  
  81. //创建一个evbuffer,用来缓冲客户端传递过来的数据

  82. struct evbuffer *buf = evbuffer_new();

  83. //创建一个bufferevent

  84. struct bufferevent *bev = bufferevent_socket_new(base_ev, client_socketfd, BEV_OPT_CLOSE_ON_FREE);

  85. //设置读取方法和error时候的方法,将buf缓冲区当参数传递

  86. bufferevent_setcb(bev, read_cb, NULL, error_cb, buf);

  87. //设置类型

  88. bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);

  89. //设置水位

  90. bufferevent_setwatermark(bev, EV_READ, 0, 0);

  91. }

  92.  
  93.  
  94. //入口主函数

  95. int main() {

  96.  
  97. WORD sockVersion = MAKEWORD(2, 2);

  98. WSADATA wsaData;

  99. if (WSAStartup(sockVersion, &wsaData) != 0)

  100. {

  101. return 0;

  102. }

  103.  
  104. int server_socketfd; //服务端socket

  105. struct sockaddr_in server_addr; //服务器网络地址结构体

  106. memset(&server_addr, 0, sizeof(server_addr)); //数据初始化--清零

  107. server_addr.sin_family = AF_INET; //设置为IP通信

  108. server_addr.sin_addr.s_addr = INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上

  109. server_addr.sin_port = htons(8001); //服务器端口号

  110.  
  111. //创建服务端套接字

  112. server_socketfd = socket(PF_INET, SOCK_STREAM, 0);

  113. if (server_socketfd < 0) {

  114. puts("socket error");

  115. return 0;

  116. }

  117.  
  118. evutil_make_listen_socket_reuseable(server_socketfd); //设置端口重用

  119. evutil_make_socket_nonblocking(server_socketfd); //设置无阻赛

  120.  
  121. //绑定IP

  122. if (bind(server_socketfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0) {

  123. puts("bind error");

  124. return 0;

  125. }

  126.  
  127. //监听,监听队列长度 5

  128. listen(server_socketfd, 10);

  129.  
  130. //创建event_base 事件的集合,多线程的话 每个线程都要初始化一个event_base

  131. struct event_base *base_ev;

  132. base_ev = event_base_new();

  133. const char *x = event_base_get_method(base_ev); //获取IO多路复用的模型,linux一般为epoll

  134. printf("METHOD:%s\n", x);

  135.  
  136. //创建一个事件,类型为持久性EV_PERSIST,回调函数为do_accept(主要用于监听连接进来的客户端)

  137. //将base_ev传递到do_accept中的arg参数

  138. struct event *ev;

  139. ev = event_new(base_ev, server_socketfd, EV_TIMEOUT | EV_READ | EV_PERSIST, do_accept, base_ev);

  140.  
  141. //注册事件,使事件处于 pending的等待状态

  142. event_add(ev, NULL);

  143.  
  144. //事件循环

  145. event_base_dispatch(base_ev);

  146.  
  147. //销毁event_base

  148. event_base_free(base_ev);

  149. return 1;

  150. }

编译,生成!