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);
}
转载于:https://www.cnblogs.com/witton/p/6868962.html
libevent使用IOCP网络模型的示例相关推荐
- WebRTC--添加IOCP网络模型支持
一.起因 webRTC在windows平台默认使用的是WSAAsyncSelect模型,该模型需要有一个windows窗口的支持,而且伸缩性.性能都比较低. 关于WSAAsyncSelect模型的介绍 ...
- 蛙蛙推荐:在c#使用IOCP(完成端口)的简单示例
蛙蛙推荐:在c#使用IOCP(完成端口)的简单示例 上次给大家发了利用winsock原生的api来做一个同步的socket服务器的例子,大致上只是贴了一些代码,相信大家这么冰雪聪明,已经研究的差不多了 ...
- 在c#使用IOCP(完成端口)的简单示例
上次给大家发了利用winsock原生的api来做一个同步的socket服务器的例子,大致上只是贴了一些代码,相信大家这么冰雪聪明,已经研究的差不多了.因为winsock的api使用在msdn或者goo ...
- windows 平台使用 VS2017 编译 libevent 源码
一 依赖库编译 先要将其依赖的库编译好,其中openssl需要编译到libevent中,编译成libevent_openssl.lib库,zlib在新版本中只有示例用到. 1)windows 平台使用 ...
- vs2017运行显示系统找不到指定的文件_windows 平台使用 VS2017 编译 libevent 源码
一 依赖库编译 先要将其依赖的库编译好,其中openssl需要编译到libevent中,编译成libevent_openssl.lib库,zlib在新版本中只有示例用到. 1)windows 平台使用 ...
- libevent编程疑难解答
出处: http://blog.csdn.net/luotuo44/article/details/39547391 前段时间阅读了libevent的源码.读毕,之前使用libevent时的一些疑问都 ...
- 在c#使用Windows IOCP(完成端口)编程研究
一:概述 (1)IOCP是什么呢? 它就是Io Completion Port的缩写,它就是MS的内核调用机制. 因为在硬件里,与驱动程序打交道都是通过协议栈进行的,并且是通过发送包请求 ...
- 网络库libevent、libev、libuv、libhv对比
网络库libevent.libev.libuv对比_小麒麟的成长之路-CSDN博客_libevent libuv Libevent.libev.libuv三个网络库,都是c语言实现的异步事件库Asyn ...
- 网络库libevent、libev、libuv对比
Libevent.libev.libuv三个网络库,都是c语言实现的异步事件库Asynchronousevent library). 异步事件库本质上是提供异步事件通知(Asynchronous Ev ...
最新文章
- 推荐!神经进化才是深度学习未来的发展之路!
- systemctl介绍
- MySQL 到底是怎么解决幻读的?
- 腾讯云linux系统结合nginx部署项目
- Django(part42)--跨站请求伪造
- 在Android中使用GIF图片
- Mac安装RocketMQ和可视化控制台教程
- go rpc安装方法
- 关于CAS服务器磁盘占用的问题,锁定目录惹的祸
- 微软Tech·Ed与中国IT行业一同成长
- php列表代码怎么做的,php项目实战:代码讲解之订单列表问题
- Spring的@Transactional事务注意事项
- 2020年能够实现强AI吗?GPT-3 是强AI吗?
- 如何修改MySQL数据库中表和表中字段的编码方式
- 标准C程序设计七---121
- 阶段3 1.Mybatis_05.使用Mybatis完成CRUD_3 Mybatis的CRUD-修改和删除操作
- Postman调接口时获取Chrome浏览器Cookie数据携带发送
- 基于php的外卖订餐系统开题报告_网上订餐系统开题报告
- 209最新100个面试问题大全及答案
- JavaScript中canvas绘制太极图案
热门文章
- Kotlin-如何创建一个好用的协程作用域
- 树莓派上操作环境安装配置
- linux 修改时区_【003】一文全面掌握Linux初始化进程(超详细)
- python中二进制文件_Python学习基础篇 -6: Python中的文件操作
- 一篇超级详细的jsp+servlet+jdbc+mysql检验登录操作(IntelliJ IDEA)
- 数据结构实验之栈与队列四:括号匹配
- 检测生成.xml文件的效果:以人脸xml为例
- 深度学习(DL)与卷积神经网络(CNN)学习笔记随笔-01-CNN基础知识点
- Java SE7新特性之try-with-resources语句
- 软件重构过程中的思维转换: 遗留代码如何变废为宝