这段时间抽空学习了一下强大的网络库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网络模型的示例相关推荐

  1. WebRTC--添加IOCP网络模型支持

    一.起因 webRTC在windows平台默认使用的是WSAAsyncSelect模型,该模型需要有一个windows窗口的支持,而且伸缩性.性能都比较低. 关于WSAAsyncSelect模型的介绍 ...

  2. 蛙蛙推荐:在c#使用IOCP(完成端口)的简单示例

    蛙蛙推荐:在c#使用IOCP(完成端口)的简单示例 上次给大家发了利用winsock原生的api来做一个同步的socket服务器的例子,大致上只是贴了一些代码,相信大家这么冰雪聪明,已经研究的差不多了 ...

  3. 在c#使用IOCP(完成端口)的简单示例

    上次给大家发了利用winsock原生的api来做一个同步的socket服务器的例子,大致上只是贴了一些代码,相信大家这么冰雪聪明,已经研究的差不多了.因为winsock的api使用在msdn或者goo ...

  4. windows 平台使用 VS2017 编译 libevent 源码

    一 依赖库编译 先要将其依赖的库编译好,其中openssl需要编译到libevent中,编译成libevent_openssl.lib库,zlib在新版本中只有示例用到. 1)windows 平台使用 ...

  5. vs2017运行显示系统找不到指定的文件_windows 平台使用 VS2017 编译 libevent 源码

    一 依赖库编译 先要将其依赖的库编译好,其中openssl需要编译到libevent中,编译成libevent_openssl.lib库,zlib在新版本中只有示例用到. 1)windows 平台使用 ...

  6. libevent编程疑难解答

    出处: http://blog.csdn.net/luotuo44/article/details/39547391 前段时间阅读了libevent的源码.读毕,之前使用libevent时的一些疑问都 ...

  7. 在c#使用Windows IOCP(完成端口)编程研究

    一:概述 (1)IOCP是什么呢? 它就是Io   Completion   Port的缩写,它就是MS的内核调用机制.    因为在硬件里,与驱动程序打交道都是通过协议栈进行的,并且是通过发送包请求 ...

  8. 网络库libevent、libev、libuv、libhv对比

    网络库libevent.libev.libuv对比_小麒麟的成长之路-CSDN博客_libevent libuv Libevent.libev.libuv三个网络库,都是c语言实现的异步事件库Asyn ...

  9. 网络库libevent、libev、libuv对比

    Libevent.libev.libuv三个网络库,都是c语言实现的异步事件库Asynchronousevent library). 异步事件库本质上是提供异步事件通知(Asynchronous Ev ...

最新文章

  1. 推荐!神经进化才是深度学习未来的发展之路!
  2. systemctl介绍
  3. MySQL 到底是怎么解决幻读的?
  4. 腾讯云linux系统结合nginx部署项目
  5. Django(part42)--跨站请求伪造
  6. 在Android中使用GIF图片
  7. Mac安装RocketMQ和可视化控制台教程
  8. go rpc安装方法
  9. 关于CAS服务器磁盘占用的问题,锁定目录惹的祸
  10. 微软Tech·Ed与中国IT行业一同成长
  11. php列表代码怎么做的,php项目实战:代码讲解之订单列表问题
  12. Spring的@Transactional事务注意事项
  13. 2020年能够实现强AI吗?GPT-3 是强AI吗?
  14. 如何修改MySQL数据库中表和表中字段的编码方式
  15. 标准C程序设计七---121
  16. 阶段3 1.Mybatis_05.使用Mybatis完成CRUD_3 Mybatis的CRUD-修改和删除操作
  17. Postman调接口时获取Chrome浏览器Cookie数据携带发送
  18. 基于php的外卖订餐系统开题报告_网上订餐系统开题报告
  19. 209最新100个面试问题大全及答案
  20. JavaScript中canvas绘制太极图案

热门文章

  1. Kotlin-如何创建一个好用的协程作用域
  2. 树莓派上操作环境安装配置
  3. linux 修改时区_【003】一文全面掌握Linux初始化进程(超详细)
  4. python中二进制文件_Python学习基础篇 -6: Python中的文件操作
  5. 一篇超级详细的jsp+servlet+jdbc+mysql检验登录操作(IntelliJ IDEA)
  6. 数据结构实验之栈与队列四:括号匹配
  7. 检测生成.xml文件的效果:以人脸xml为例
  8. 深度学习(DL)与卷积神经网络(CNN)学习笔记随笔-01-CNN基础知识点
  9. Java SE7新特性之try-with-resources语句
  10. 软件重构过程中的思维转换: 遗留代码如何变废为宝