环境配置
下载 Libevent
官网地址:http://libevent.org/
编译 Libevent 库
- 解压libevent-2.1.11-stable.tar.gz
- 打开开始菜单,找到Vistual Studio 本机工具命令提示符
3. cd进入解压后的 libevent-2.1.11-stable 目录下
4. 执行命令: nmake /f Makefile.nmake
如果报错:f:\lib\libevent-2.1.11-stable\minheap-internal.h(73): error C2065: “UINT32_MAX”: 未声明的标识符
在该文件(minheap-internal.h)中添加 #include "stdint.h"
再次编译,会有警告,没关系。
Visual Studio 使用 Libevent
上面 Libevent 编译完成后,会在 libevent-2.1.11-stable 目录下生成三个 .lib 的文件,分别是 libevent.lib libevent_core.lib libevent_extras.lib。把他们拷贝出来待用。
使用 Visual Studio 建立一个 Win32 控制台空项目,建立完成后首先在项目目录下新建一个DEPS文件夹,DEPS下建include和lib文件夹,用来存放 .h 头文件和 .lib 库文件(熟悉的人目录结构你可以自己规划,我这样写只为新手入门准备,可以参考学习,后面熟悉了随便自己怎么改)。
随后,拷贝libevent-2.1.11-stable\include 和 libevent-2.1.11-stable\WIN32-Code 所有文件,到 include 目录,此时会出现重名目录的情况,直接覆盖就可以了,实际里面的文件不会重复。
然后拷贝编译好的三个 .lib 文件到 lib 目录下。
需要的文件我们都放到项目目录下了,接下来就是在项目中引入这两个目录。在项目上 右键-属性。
点击 VC++目录,分别在包含目录中引入项目目录下的 include 文件夹、在库目录中引入 lib 文件夹。
在 C/C+±代码生成 中,将 运行库 在 Debug 模式下修改为 多线程调试 (/MTd),在 Release 模式下修改为 多线程调试 (/MT)。
在 链接器-输入,附加依赖库 中分别添加三个 lib 文件和 socket 所需的库文件。
以上环境我们就搭建好了,接下来就是下一段代码来测试一下了。在项目中新建一个 mian.c 文件,输入一下代码编译并运行。
使用 Libevent
采用 bufferevent 实现多线程架构
使用 libevent 网络库实现了一个游戏服务器引擎,在此记录下其中遇到的一个问题。
我在设计服务器上选择把逻辑和网络分线程,线程之间通信使用队列。但是这样做会有个问题,当逻辑线程想要主动的发一个数据包的时候,网络线程此时可能还阻塞在等待网络 IO 的系统调用上(比如说 epol l)。如果不做特殊处理的话,此时消息包就会一直积压在缓冲区中,直到下一次网络线程从挂起的系统调用返回(比如来了一个消息包)。因此,当逻辑线程发送消息包的时候(bufferevent_write)需要一种唤醒机制,让网络线程从 epoll 等系统调用中返回并处理发送消息包逻辑。
libevent 相关的 api 很简单并且只有一个:evthread_use_windows_threads() 。
函数 evthread_use_windows_threads() 的调用必须在初始化 event_base 之前。在此之后,无需再做别的事情,逻辑线程在执行 bufferevent_write 的时候,libevent 就会自动唤醒网络线程的事件循环,并执行发送数据。
#ifdef WIN32
evthread_use_windows_threads();
#endif
#ifdef _EVENT_HAVE_PTHREADS
evthread_use_pthreads();
#endif
struct event_base* base = event_base_new();