ACE(Adaptive Communication Environment)是一个开源的、面向对象的工具包和框架,旨在简化复杂网络应用和服务的开发。它提供了一个丰富的集合,包括通信软件模式的实现、服务、以及用于并发编程、事件调度、线程池管理等的类库。ACE 支持广泛的平台和操作系统,使其成为构建高性能、可移植的网络应用程序的理想选择。
ACE 的主要特点
- 跨平台支持:能够在多种操作系统上运行,包括 Windows、Linux、Unix 等。
- 丰富的通信协议支持:支持 TCP/IP、UDP、SCTP 等多种网络协议。
- 灵活的服务配置:通过使用 Reactor 和 Proactor 模式,能够方便地处理异步事件。
- 高效的并发控制:提供了线程池、互斥锁、读写锁等多种同步机制来帮助开发者编写高效且安全的多线程程序。
- 内存管理:提供自动化的内存管理工具,减少内存泄漏的风险。
基本概念与组件
-
Reactor 模式:一个事件处理循环,允许应用程序注册感兴趣的事件,并在这些事件发生时得到通知。适用于处理大量短连接或需要快速响应的场景。
-
Proactor 模式:一种异步 I/O 模型,允许执行非阻塞操作并在线程池中处理完成的通知。适用于长连接或需要高性能的场景。
-
ACE_Task:实现了主动对象(Active Object)的概念,使得每个任务都可以在独立的线程中运行,适合于需要长期运行的任务或后台处理。
-
Connector/Acceptor 模式:用于解耦网络连接建立过程中的客户端和服务器端逻辑,便于扩展和维护。
使用 ACE 创建一个简单的 TCP 服务器
下面是一个使用 ACE 构建的基本 TCP 服务器示例:
#include "ace/INET_Addr.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/Reactor.h"
#include "ace/Acceptor.h"
#include "ace/Svc_Handler.h"
#include <iostream>
class Echo_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> {
public:
// 当有数据到达时被调用
int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE) override {
char buf[1024];
size_t len = this->peer().recv(buf, sizeof(buf));
if (len > 0) {
std::cout << "Received: " << std::string(buf, len) << std::endl;
this->peer().send(buf, len); // 回显消息
} else {
this->reactor()->remove_handler(this);
delete this; // 关闭连接并删除自身
}
return 0;
}
// 连接关闭时被调用
int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE,
ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK) override {
this->peer().close();
return 0;
}
};
typedef ACE_Acceptor<Echo_Handler, ACE_SOCK_ACCEPTOR> Echo_Acceptor;
int main() {
ACE_INET_Addr port_to_listen(12345, ACE_LOCALHOST);
Echo_Acceptor acceptor(port_to_listen);
ACE_Reactor::instance()->run_reactor_event_loop();
return 0;
}
ACE_Task
ACE_Task<ACE_MT_SYNCH> 是 ACE(Adaptive Communication Environment)框架中的一个模板类,用于实现多线程任务处理。这个类提供了对多线程的支持,并允许你创建可以主动运行的线程,以及通过消息队列与其他线程进行通信的任务。ACE_MT_SYNCH 是一个模板参数,指定了使用多线程同步机制。
基本概念
- ACE_Task:这是一个核心类,提供了一个简单的接口来实现主动对象(active objects)。主动对象是指那些在其自己的控制线程中执行操作的对象。
- ACE_MT_SYNCH:这是一个模板参数,它决定了在多线程环境中使用的同步机制。使用
ACE_MT_SYNCH作为模板参数意味着将使用适合多线程环境的锁和其他同步原语。
实现一个多线程任务
以下是一个简单的例子,展示了如何使用 ACE_Task<ACE_MT_SYNCH> 来创建和运行一个多线程任务。
示例代码
#include "ace/config.h"
#include "ace/Task.h"
#include <iostream>
#include <ace/Init_ACE.h>
class MyTask : public ACE_Task<ACE_MT_SYNCH> {
public:
//MyTask() = default;
MyTask(int maxThread)
: m_maxThread(maxThread)
, m_thr_ids(new ACE_thread_t[maxThread])
{
}
int open(void* = nullptr) override {
// Called when activate() is invoked. You can perform any initialization here.
std::cout << "Task started." << std::endl;
msg_queue()->high_water_mark(50 * 1024 * 1024);
///* -- WSAStartup -- */
WORD version = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(version, &data) != 0)
{
return -1;
}
return activate(
THR_NEW_LWP, // -> flags
m_maxThread, // -> n_threads
0, // -> force_active
ACE_DEFAULT_THREAD_PRIORITY, // -> priority
-1, // -> grp_id
NULL, // -> task
NULL, // -> thread_handles
NULL, // -> stack
NULL, // -> stack_size
m_thr_ids, // -> thread_ids
NULL // -> thr_name
);
return 0;
}
int svc() override {
// The main thread loop of the task.
for (int i = 0; i < 5; ++i) {
std::cout << "Working in thread: " << thr_mgr()->thr_self()/*this->thr_self()*/ << std::endl;
ACE_OS::sleep(1); // Simulate work by sleeping for a second
}
std::cout << "Thread finished." << std::endl;
return 0;
}
int close(u_long flags = 0) override {
// Called when the task is shutting down.
std::cout << "Task closed." << std::endl;
return 0;
}
private:
int m_maxThread; /// 线程数
ACE_thread_t *m_thr_ids; /// 线程ID
};
int main(int argc, char* argv[])
{
MyTask my_task(3);
// Activate the task with 3 threads.
//if (my_task.activate(THR_NEW_LWP | THR_JOINABLE, 3) == -1) {
// std::cerr << "Failed to activate task" << std::endl;
// return -1;
//}
my_task.open();
// Wait for all threads to finish their work before exiting.
my_task.wait();
std::cout << "All threads have completed their work." << std::endl;
return 0;
}
关键函数分析
- open 方法:当调用
activate()方法时会触发此方法。你可以在这里进行一些初始化工作。 - svc 方法:这是每个线程的主循环。在这个方法中,你可以编写需要并行执行的代码。在这个例子中,我们简单地打印了当前线程ID,并模拟了一秒钟的工作。
- close 方法:当任务关闭时被调用,可以用来清理资源。
- activate 方法:启动任务,参数包括线程属性和要创建的线程数。在这个例子中,我们创建了3个线程。
- wait 方法:等待所有由
activate()创建的线程完成它们的工作。
【注】:VS工程配置,预处理器定义添加
_WINSOCK_DEPRECATED_NO_WARNINGS;
_CRT_SECURE_NO_WARNINGS;
WIN32;
_WIN32;
1658

被折叠的 条评论
为什么被折叠?



