当前位置:   article > 正文

网络库的使用(libevent、ACE、boost::asio)_ace网络库

ace网络库

几种网络库比较
react(同步)、proact(异步)模式

1. ACE(Adaptive Communication Environment 自适配通信环境)

ACE下载地址:https://download.dre.vanderbilt.edu/
Github地址:https://github.com/DOCGroup/ACE_TAO

1.1 相关书籍

ACE书籍介绍
POSA:
面向模式的软件架构(卷1):模式系统
面向模式的软件架构(卷2):并发和联网对象模式
面向模式的软件架构(卷3):资源管理模式
面向模式的软件架构(卷4):分布式计算的模式语言
面向模式的软件架构(卷5):模式与模式语言
C++NP:
C++网络编程(卷1):运用ACE和模式消除复杂性
C++网络编程(卷2):基于ACE和框架的系统化复用
APG:(The ACE Programmers Guide)
ACE程序员指南:网络与系统编程的使用设计模式
上中下:
上篇:ACE技术论文集
中篇:ACE程序员教程
下篇:ACE应用实例

1.2 相关文章

ACE网络编程 --ACE库入门:中篇-ACE程序员教程
初学者:ACE学习
ACE系列文章
ACE从入门到精通V9.5

1.3 Qt + ACE

.pro:

win32:ACE_ROOT = D:\ACE
win32:INCLUDEPATH += $$ACE_ROOT\include
win32:DEFINES += ACE_AS_STATIC_LIBS
win32:DEFINES += ACE_DOESNT_DEFINE_MAIN
win32:LIBS += $$ACE_ROOT\lib\libACE.a -lws2_32 -lmswsock -liphlpapi -lwsock32 -lnetapi32
  • 1
  • 2
  • 3
  • 4
  • 5
#ifndef _SCK_SERVER_H
#define _SCK_SERVER_H
 
#include <ace/Init_ACE.h>
 
class Sck_Server
{
public:
    Sck_Server()
    {
        ACE::init();
    }
   ~Sck_Server()
    {
        ACE::fini();
    }
    int start() const;
    void stop() const;
};
 
#endif /* _SCK_SERVER_H */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

由于添加了宏定义ACE_DOESNT_DEFINE_MAIN会出现"WSA Startup not initialized"的错误提示!而且服务器不能监听。
ACE定义了main这个宏,该宏会创建一个叫ACE_Main_Base对象来初始化网络,即调用WSAStartup函数。所以要避免这个问题,要么使用ACE定义的这个main宏作为程序入口,要么自己手动调用ACE_OS::socket_init或者WSAStartup初始化。
ACE如何融入QT中(解决定义ACE_DOESNT_DEFINE_MAIN后,无法开启TCP监听)

2. libevent

官网下载:https://libevent.org/ (若下不了,是因为上不了github)
服务器并发编程–libevent【bilibili】
libevent视频分散
Libevent实现简单TCP服务端及客户端
libevent多线程模式(memcached中)
libevent之bufferevent中获取客户端ip

2.1 使用全局base

#include "event.h"
struct event ev;			//创建事件
//这里也可接一下返回值,struct event_base* event_init(void)中创建的base同时存到全局变量current_base
event_init();				//创建事件集合,
event_set(&ev, fd, EV_READ|EV_PRESIST, fifo_read, NULL);//绑定事件与fd,参数(事件,文件描述符,事件类型,回调函数,回调参数)
event_add(&ev,NULL);		//将事件加入到集合(队列)中
event_dispatch();			//监听事件(类似消息循环),没有事件可监听则退出, 不加EV_PRESIST,则触发一次便清除

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.2 使用自己的base

struct event ev;
struct event_base *base = event_base_new();
event_assign(&ev, base, SIGINT, EV_SIGNAL|EV_PERSIST, signal_handler, NULL);
event_add(&ev,NULL);
event_base_dispatch(base);
event_base_free(base);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

event指针方式:

struct event *ev = NULL; 
struct timeval tv;
ev = event_new(base, fd, EV_READ|EV_PERSIST, cb, NULL);
tv.tv_sec = 1;
tv.tv_usec = 0;
event_add(ev, &tv);		//超时
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
struct event_base *base = NULL;
struct event_config *cfg = NULL;
cfg = event_config_new();
base = event_base_new_with_config(cfg);
event_base_free(base);
event_config_free(cfg);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.3 socket应用

#include <event.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = 8000;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

struct event_base *base = event_base_new();
//参数(事件集合、监听回调函数(已accept了),回调参数,类型(释放监听对象时关闭socket|端口重复使用),监听队列长度,绑定地址信息)
struct evconnlistener *listener = evconnlistener_new_bind(base, listener_cb, NULL, 
       									LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 10, 
       									(struct sockaddr*)&server_addr, sizeof(server_addr));
event_base_dispatch(base);
evconnlistener_free(listener);
event_base_free(base);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

监听回调:

void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int socklen, void *arg)
{
	printf("接受%d的连接\n", fd);
	struct event_base *base = arg;
	struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);  //参数(eventbase,fd,释放bufferevent则关闭连接)
	//参数(bufferevent, 读回调,写回调, 其他回调,回调参数)
	bufferevent_setcb(bev, read_cb, NULL, event_cb, &fd);	//(void *)fd  (void*)(&fd)
	bufferevent_enable(bev, EV_READ);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

读回调、其他回调:

void read_cb(struct bufferevent *bev, void *ctx)
{
	int fd = *(int *)ctx;
	char buf[1024]={0};
	size_t ret = bufferevent_read(bev, buf,sizeof(buf));
	if(ret < 0)
	{
		printf("bufferevent_read error!\n");
	}
	else
	{		
		printf("read from %d: %s\n", fd, buf);
	}
}

void event_cb(struct bufferevent *bev, short what, void *ctx)
{
	printf("异常发生: %x", what);
	int fd = *(int *)ctx;
	if(what & BEV_EVENT_EOF)
	{
		printf("客户端%d下线\n", *(int *)ctx);
		bufferevent_free(bev);	//释放bufferevent关闭socket
	}
	else
	{}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

3. libevent源码分析

3.1 源码文件说明

  • 1)头文主要就是 event.h:事件宏定义、接口函数声明,主要结构体 event 的声明;
  • 2)内部头文件
    xxx-internal.h:内部数据结构和函数,对外不可见,以达到信息隐藏的目的;
  • 3) libevent 框架
    event.c: event 整体框架的代码实现;
  • 4)对系统 I/O 多路复用机制的封装
    epoll.c:对 epoll 的封装;
    select.c:对 select 的封装;
    devpoll.c:对 dev/poll 的封装;
    kqueue.c:对 kqueue 的封装;
  • 5)定时事件管理
    min-heap.h:其实就是一个以时间作为 key 的小根堆结构;
  • 6)信号管理
    signal.c:对信号事件的处理;
  • 7)辅助功能函数
    evutil.h 和 evutil.c:一些辅助功能函数,包括创建 socket pair 和一些时间操作函数:加、减
    和比较等。
  • 8)日志
    log.h 和 log.c: log 日志函数
  • 9)缓冲区管理
    evbuffer.c 和 buffer.c: libevent 对缓冲区的封装;
  • 10)基本数据结构
    compat\sys 下的两个源文件:
    queue.h :是 libevent 基本数据结构的实现,包括链表,双向链表,队列等;
    _libevent_time.h:一些用于时间操作的结构体定义、函数和宏定义;
  • 11)实用网络库
    http 和 evdns:是基于 libevent 实现的 http 服务器和异步 dns 查询库;

4. asio库

官网:https://think-async.com/Asio/
介绍:Boost.Asio网络编程
最重要的类:io_service ( io_context )

5.muduo

muduo缓冲区Buffer类

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/923236
推荐阅读
相关标签
  

闽ICP备14008679号