libevent是一个基于事件触发的网络库,memcached底层也是使用libevent库,今天学习下。

总体来说,libevent有下面一些特点和优势:
* 统一数据源, 统一I/O事件,信号和定时器这三种事件;

* 可移植,跨平台支持多种I/O多路复用技术, epoll、poll、dev/poll、select 和kqueue 等;

* 对并发编程支持,避免竞态条件;


* 高性能,由事件驱动;


* 轻量级,专注于网络;

libevent有下面几大部分组成:

* 事件管理包括各种IO(socket)、定时器、信号等事件,也是libevent应用最广的模块;

* 缓存管理是指evbuffer功能;

* DNS是libevent提供的一个异步DNS查询功能;

* HTTP是libevent的一个轻量级http实现,包括服务器和客户端

一些资料:
* libevent官网:http://libevent.org/ 
* libevent API:http://www.monkey.org/~provos/libevent/doxygen-2.0.1/index.html

// =============================================================================================

下面写了2个简单的使用例子,一个是定时器,一个是TCP服务器,都只涉及到libevent的事件管理模块。

一、简单定时器:实现程序每秒输出一个“Game Over!”

event_init() => evtimer_set() => event_add() =>event_dispatch()


​​

1. #include <stdio.h>  
2. #include <iostream>
3.
4. // libevent头文件
5. #include <event.h>
6. using namespace std;
7.
8. // 定时事件回调函数
9. void onTime(int sock, short event, void *arg)
10. {
11. "Game Over!" << endl;
12.
13. struct timeval tv;
14. tv.tv_sec = 1;
15. tv.tv_usec = 0;
16. // 重新添加定时事件(定时事件触发后默认自动删除)
17. struct event*)arg, &tv);
18. }
19.
20. int main()
21. {
22. // 初始化
23. event_init();
24.
25. struct event evTime;
26. // 设置定时事件
27. evtimer_set(&evTime, onTime, &evTime);
28.
29. struct timeval tv;
30. tv.tv_sec = 1;
31. tv.tv_usec = 0;
32. // 添加定时事件
33. event_add(&evTime, &tv);
34.
35. // 事件循环
36. event_dispatch();
37.
38. return 0;
39. }


编译并执行,编译加 -levent:



​​

1. gapp_devnet_1:/data/home/andyawang/code/2013_11/LibeventTest # mv time.cpp timer.cpp  
2. gapp_devnet_1:/data/home/andyawang/code/2013_11/LibeventTest # g++ -o timer timer.cpp -levent
3. gapp_devnet_1:/data/home/andyawang/code/2013_11/LibeventTest # ./timer
4. Game Over!
5. Game Over!
6. Game Over!
7. Game Over!



二、TCP服务器:

实现监听本机8888端口并输出客户端发送过来的信息

event_base_new()=>event_set()=>event_base_set()=>event_add()=>event_base_dispatch()


​​



1. #include <stdio.h>  
2. #include <string.h>
3. #include <iostream>
4. #include <sys/socket.h>
5. #include <netinet/in.h>
6. #include <arpa/inet.h>
7. #include <netdb.h>
8.
9. #include <event.h>
10. using namespace std;
11.
12. // 事件base
13. struct event_base* base;
14.
15. // 读事件回调函数
16. void onRead(int iCliFd, short iEvent, void *arg)
17. {
18. int iLen;
19. char buf[1500];
20.
21. iLen = recv(iCliFd, buf, 1500, 0);
22.
23. if (iLen <= 0) {
24. "Client Close" << endl;
25.
26. // 连接结束(=0)或连接错误(<0),将事件删除并释放内存空间
27. struct event *pEvRead = (struct event*)arg;
28. event_del(pEvRead);
29. delete pEvRead;
30.
31. close(iCliFd);
32. return;
33. }
34.
35. buf[iLen] = 0;
36. "Client Info:" << buf << endl;
37. }
38.
39. // 连接请求事件回调函数
40. void onAccept(int iSvrFd, short iEvent, void *arg)
41. {
42. int iCliFd;
43. struct sockaddr_in sCliAddr;
44.
45. sizeof(sCliAddr);
46. struct sockaddr*)&sCliAddr, &iSinSize);
47.
48. // 连接注册为新事件 (EV_PERSIST为事件触发后不默认删除)
49. struct event *pEvRead = new event;
50. event_set(pEvRead, iCliFd, EV_READ|EV_PERSIST, onRead, pEvRead);
51. event_base_set(base, pEvRead);
52. event_add(pEvRead, NULL);
53. }
54.
55. int main()
56. {
57.
58. int iSvrFd;
59. struct sockaddr_in sSvrAddr;
60.
61. sizeof(sSvrAddr));
62. sSvrAddr.sin_family = AF_INET;
63. "127.0.0.1");
64. sSvrAddr.sin_port = htons(8888);
65.
66. // 创建tcpSocket(iSvrFd),监听本机8888端口
67. iSvrFd = socket(AF_INET, SOCK_STREAM, 0);
68. struct sockaddr*)&sSvrAddr, sizeof(sSvrAddr));
69. listen(iSvrFd, 10);
70.
71. // 初始化base
72. base = event_base_new();
73.
74. struct event evListen;
75. // 设置事件
76. event_set(&evListen, iSvrFd, EV_READ|EV_PERSIST, onAccept, NULL);
77. // 设置为base事件
78. event_base_set(base, &evListen);
79. // 添加事件
80. event_add(&evListen, NULL);
81.
82. // 事件循环
83. event_base_dispatch(base);
84.
85. return 0;
86. }





​​cocos2dx加libevent库​​



路径: $path = cocos2dx/platform/third_party

1.win32

   将生成的libevent_core.lib,libevent_extras.lib放到$path/win32/libraries中

   头文件event2和event-config.h 放到$path/win32/libevent中

   VS中设置include path和 add lib

 

2.ios

   生成IOS平台的库文件(libevent_core.a,libevent_extra.a,libevent_pthreads.a)放到$path/ios/libraries中,注意:是IOS的库文件,不是linux的

   头文件放到$path/ios/libevent

  xcode中增加head search path 和 添加刚才的3个库文件

  库文件找了也是用libevent的OnionBrowser生成

 

3.android

   android实在在多坑了,搞了好久才搞定

  问题列表

   1).logcat输出调试:在proj.android/jni/andoird.mk 中加入LOCAL_CFLAGS := -DCOCOS2D_DEBUG=1

   2).在NDK BUILD过程中提示htons找不到,查了好久发现是自定义的endian.h和系统文件重名

   3).加好后bufferevent_socket_connect返回-1,连接失败.

        原因是没有网络权限,在proj.android/AndroidManifest.xml中加上 权限申请

        <uses-permission android:name="android.permission.INTERNET"></uses-permission>

   4) ndk build完后连接失败,找不到一些库函数,原因是在build libevent.a的时候注释了一段,链接符"\"结果把后面的全都注释掉了,

       导致libevent.包不完整

 

    添加库:在网上git找了个andoird用的libevent,用ndk build好后放到$path/android/libevent中,.mk文件写法跟libcurl一样

   链接:​​https://github.com/ventureresearch/libevent/tree/master​

   然后在proj.android/jni/andoird.mk中加上LOCAL_STATIC_LIBRARIES += cocos_event_static;

             $(call import-module,cocos2dx/platform/third_party/android/prebuilt/libevent)