libevent使用IOCP网络模型的示例
这段时间抽空学习了一下强大的网络库libevent,其使用标准C语言编写,支持Windows、Linux、Mac等等主流操作系统,早期版本不支持Windows的IOCP,最新版本已经添加上了,在网上找了一下资料,发现使用IOCP的libevent示例太少,于是结合网上的资料,自己整理编写了一下libevent使用IOCP的小例子。该示例同时支持IPV4以及IPV6的连接。
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- //包含所需要的头文件
- #include "event2/event.h"
- #include "event2/listener.h"
- #include "event2/bufferevent.h"
- #include "event2/thread.h"
- #include "event2/buffer.h"
- #ifdef __cplusplus
- };
- #endif
- #ifdef _MSC_VER
- #pragma comment(lib,"ws2_32.lib")
- #pragma comment(lib,"libevent_core.lib")
- #endif
- //监听回调函数
- void listener_cb(evconnlistener *listener, evutil_socket_t fd,
- struct sockaddr *sock, int socklen, void *arg);
- //从Socket接收消息的回调函数
- void socket_read_cb(bufferevent *bev, void *arg);
- //从Socket事件的回调函数
- void socket_event_cb(bufferevent *bev, short events, void *arg);
- int main()
- {
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
- /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
- wVersionRequested = MAKEWORD(2, 2);
- //这里必须初始化网络,不然会创建Socket失败
- err = WSAStartup(wVersionRequested, &wsaData);
- if (err != 0) {
- /* Tell the user that we could not find a usable */
- /* Winsock DLL. */
- printf("WSAStartup failed with error: %d\n", err);
- return 1;
- }
- struct sockaddr_in sin;
- memset(&sin, 0, sizeof(struct sockaddr_in));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(2000);
- struct sockaddr_in6 sin6;
- memset(&sin6, 0, sizeof(struct sockaddr_in6));
- sin6.sin6_family = AF_INET6;
- sin6.sin6_port = htons(2000);
- //告诉libEvent使用Windows线程
- //这句是必须的,不然会导致event_base_dispatch时一直处于Sleep状态,无法正常工作
- evthread_use_windows_threads();
- struct event_config* cfg = event_config_new();
- event_config_set_flag(cfg,EVENT_BASE_FLAG_STARTUP_IOCP);
- //根据CPU实际数量配置libEvent的CPU数
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- event_config_set_num_cpus_hint(cfg,si.dwNumberOfProcessors);
- event_base *base;
- base = event_base_new_with_config(cfg);
- event_config_free(cfg);
- // 绑定并监听IPV4端口
- evconnlistener *listener = evconnlistener_new_bind(base, listener_cb, base,
- LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,
- 10, (struct sockaddr*)&sin,
- sizeof(sin));
- // 绑定并监听IPV6端口
- evconnlistener *listener6 = evconnlistener_new_bind(base, listener_cb, base,
- LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,
- 10, (struct sockaddr*)&sin6,
- sizeof(sin6));
- //事件分发处理
- event_base_dispatch(base);
- evconnlistener_free(listener);
- evconnlistener_free(listener6);
- event_base_free(base);
- WSACleanup();
- return 0;
- }
- //一个新客户端连接上服务器了
- //当此函数被调用时,libevent已经帮我们accept了这个客户端。该客户端的
- //文件描述符为fd
- void listener_cb(evconnlistener *listener, evutil_socket_t fd,
- struct sockaddr *sock, int socklen, void *arg)
- {
- char Buffer[256];
- sockaddr_in* addr = (sockaddr_in*)sock;
- evutil_inet_ntop(addr->sin_family,&addr->sin_addr,Buffer,sizeof(Buffer));
- printf("accept a client %d,IP:%s\n", fd,Buffer);
- event_base *base = (event_base*)arg;
- //为这个客户端分配一个bufferevent
- bufferevent *bev = bufferevent_socket_new(base, fd,
- BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE);
- bufferevent_setcb(bev, socket_read_cb, NULL, socket_event_cb, NULL);
- bufferevent_enable(bev, EV_READ | EV_PERSIST);
- }
- void socket_read_cb(bufferevent *bev, void *arg)
- {
- char msg[4096];
- size_t len;
- // 这里一行一行的读取
- char* p = evbuffer_readln(bufferevent_get_input(bev),&len,EVBUFFER_EOL_ANY);
- if(p)
- {
- // 如果输入exit或者quit则退出程序
- // 可以使用event_base_loopexit或者event_base_loopbreak
- // 它们的区别是前者会把事件处理完才退出,后者是立即退出
- if(!strcmp(p,"exit"))
- event_base_loopexit(bufferevent_get_base(bev),NULL);
- else if (!strcmp(p,"quit"))
- event_base_loopbreak(bufferevent_get_base(bev));
- printf("recv data:%s\n", p);
- int n = sprintf_s(msg,"srv recv data:%s\n",p);
- //发送消息给客户端
- bufferevent_write(bev, msg, n );
- // 这里记得把分配的内存释放掉,不然会内存泄漏
- free(p);
- }
- }
- void socket_event_cb(bufferevent *bev, short events, void *arg)
- {
- if (events & BEV_EVENT_EOF)
- printf("connection closed\n");
- else if (events & BEV_EVENT_ERROR)
- printf("some other error\n");
- //这将自动close套接字和free读写缓冲区
- bufferevent_free(bev);
- }
libevent使用IOCP网络模型的示例的更多相关文章
- 几个网络模型的示例代码(BlockingModel、OverlappedModel、WSAEventSelect、CompletionRoutine)..c++
作者的blog:猪)的网络编程世界 几个网络模型的示例代码代码包括了下面几个模型的示例:BlockingModel(阻塞模式).OverlappedModel(基于事件的重叠I/O).WSAEvent ...
- Libevent源码分析 (1) hello-world
Libevent源码分析 (1) hello-world ⑨月份接触了久闻大名的libevent,当时想读读源码,可是由于事情比较多一直没有时间,现在手头的东西基本告一段落了,我准备读读libeven ...
- 简单对比 Libevent、libev、libuv
Libevent.libev.libuv三个网络库,都是c语言实现的异步事件库Asynchronousevent library). 异步事件库本质上是提供异步事件通知(Asynchronous Ev ...
- windows 平台使用 VS2017 编译 libevent 源码
一 依赖库编译 先要将其依赖的库编译好,其中openssl需要编译到libevent中,编译成libevent_openssl.lib库,zlib在新版本中只有示例用到. 1)windows 平台使用 ...
- 网络库libevent、libev、libuv对比
Libevent.libev.libuv三个网络库,都是c语言实现的异步事件库Asynchronousevent library). 异步事件库本质上是提供异步事件通知(Asynchronous Ev ...
- libevent编程疑难解答
http://blog.csdn.net/luotuo44/article/details/39547391 转载请注明出处:http://blog.csdn.net/luotuo44/article ...
- EQueue - 一个纯C#写的分布式消息队列介绍2
一年前,当我第一次开发完EQueue后,写过一篇文章介绍了其整体架构,做这个框架的背景,以及架构中的所有基本概念.通过那篇文章,大家可以对EQueue有一个基本的了解.经过了1年多的完善,EQueue ...
- 发布一个UDP调试助手
UDP协议适用于那种频繁通信,但是可以容忍一些丢包的应用,比如GPS的定位应用. 调试UDP助手,可以定时发送,输出文本, 记录收到时间. 1. 该工具基于IOCP网络模型,调试UDP服务使用的一个工 ...
- windows下的IO模型之事件选择(WSAEventSelect)模型
异步选择模型类似的是,它也允许应用程序在一个或多个套接字上,接收以事件为基础的网络事件通知.对于异步选择模型采用的网络事件来说,它们均可原封不动地移植到事件选择模型.事件选择模型和异步选择模型最主要的 ...
随机推荐
- CSS和jQuery分别实现图片无缝滚动效果
一.效果图 二.使用CSS实现 <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g ...
- 前端用vue,后端需要nodejs吗?
其实用脚趾头想想也知道:后端用不用node,和前端用不用vue,二者完全没关系. 那为何用vue和vue插件开发前端的时候,经常需要各种npm install呢?为何要在本地安装node环境? 本地需 ...
- pickle模块 和json模块
pickle和json序列号 json模块是所有语言通用的,可以用来把一些数据转成字符串存储在文件中 import json l=[,,] with open('t3',mode='w',encodi ...
- printf sscanf进阶
printf ; printf (3d", a);//将打印 035 printf(“%-*s”, width, string): “*”: 在这里用width代替,其实和printf(“% ...
- 7、执行 suite 后,result.html 测试报告中,测试结果全部显示为通过原因分析
测试用例中,断言 异常后,必须 raise 抛出异常, 若无raise ,则测试报告中测试结果全部显示为通过. 抛出后,显示实际测试结果,通过/未通过 __author__ = 'Administra ...
- Dubbo---注册中心
1.Multicast 注册中心 1.1 Multicast 注册中心 不需要启动 任何中心节点,只要广播地址一样,就可以互相发现. 1.2 1.3 配置 2.zookeeper 注册中心( ...
- mac上安装mamp集成环境
深知mac配置环境是个坑,本人之前用的是xampp因为近期需要mongodb扩展,死活装不明白,索性就换了一个集成环境,在网上找了好多,最后选择了mamp 因为正版的要收费,所以在下载了N个以后终于找 ...
- 每天一个Linux命令:ls(1)
ls ls命令用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录). 格式 ls [-alrtAFR] [name...] 参数选项 参数 备注 -a 列出目录下的所有文件,包括以 . ...
- centos7安装kylo0.10.1
安装环境centos7,kylo版本0.10.1 常用的链接地址 kylo官网:https://kylo.io/ kylo文档:https://kylo.readthedocs.io/ 下载地址 官网 ...
- mybatis的核心对象图解