转自:http://www.cnblogs.com/dubingsky/archive/2009/07/22/1528292.html
ACE编译
1. 设置环境变量
- 在操作系统添加一个名为ACE_ROOT的用户环境变量,值为刚才ace的解压路径D:\Develop\ACE_wrappers。
- 添加用户的Path环境变量,值为%ACE_ROOT%\lib,这样才能保证系统能找到ace生成的动态连接库。
- 设置VS2005的C++开发项目信息,依次打开菜单 工具-选项-项目和解决方案-VC++目录 ,在右侧目录列表中选择"包含目录",添加$(ACE_ROOT),在右侧目录列表中选择"库文件",添加$(ACE_ROOT)\lib。
2. 在 ACE_wrappers\ace目录下创建 config.h 文件,写入: #include "ace/config-win32.h"
Code 3. 如果你希望使用标准的 C++ 头文件(例如 iostream、cstdio 等)在 #include "ace/config-win32.h" 前加入: #define ACE_HAS_STANDARD_CPP_LIBRARY 1 4. 如果你希望使用 MFC 库,那么 config.h 中加入: #define ACE_HAS_MFC 1 如果你希望使用 MFC 静态库,那么加入: #define ACE_USES_STATIC_MFC 5. 如果你希望编译静态版本的 ACE 库,那么在 config.h 中加入: #define ACE_AS_STATIC_LIBS 6. 如果你希望减少静态库的大小,可以禁止使用 inline,在 config.h 的 #include "ace/config-win32.h" 前加入: #define ACE_NO_INLINE
ACE结构简介
1)ACE OS adaptation层:封装了 OS API,对上层提供 OS平台无关的接口。
2)C++ wrapper facades层:位于 OS adaptation之上,提供了与之相似的功能,这些功能使用 C++的类封装起来,而不是 C 语言 API。每个 wrapper facade都包含一个或者一个以上的类。我们可以有选择的继承、聚合这些 wrapper facade。
3)框架层(Framework layer)
框架层在 C++ wrapper facades层之上,它集成和扩充了 wrapper facade类。
事件多路分离和分发框架
ACE Reactor 和 ACE Proactor 实现了 Reactor 模式和 Proactor模式。
连接建立和服务初始化框架
ACE Acceptor-Connector框架实现了 Acceptor-Connector模式。
并发框架
ACE 提供了 Task框架实现了并发模式。
服务配置框架
ACE 的服务配置框架实现了 Component Configurator模式。
流框架
ACE 的流框架实现了 Pipes and Fiters模式。
4)ACE网络组件层
组件(component)就是软件系统中被封装的一个部分,ACE发行包中的组件用于提供以下功能:
演示 ACE
提供常见网络服务的可复用实现。如提供日志记录、时间同步等服务的可复用实现。
线程的创建与管理
一.线程入口函数
所有线程必须从一个指定的函数开始执行,该函数称为线程函数,它必须具有下列原型: void* worker(void *arg) {} 该函数输入一个void *型的参数,可以在创建线程时传入。 注意:所有的线程启动函数(方法)必须是静态的或全局的(就如同直接使用OS线程API时所要求的一样)。
二.线程基本操作
1.创建一个线程
一个进程的主线程是由操作系统自动生成,如果你要让一个主线程创建额外的线程,可以通过ACE_Thread::spawn()实现,该函数一般的使用方式如下:
ACE_thread_t threadId;
ACE_hthread_t threadHandle;
ACE_Thread::spawn(
(ACE_THR_FUNC)worker, //线程执行函数
NULL, //执行函数参数
THR_JOINABLE | THR_NEW_LWP,
&threadId,
&threadHandle
);
ACE_Thread::spawn((ACE_THR_FUNC)worker)使用其默认参数,来创建一个worker的线程。
ACE_Thread::spawn_n函数来创建多个线程。
2.终止线程
在线程函数体中ACE_Thread::exit()调用即可终止线程执行。
3.设定线程的相对优先级
当一个线程被首次创建时,它的优先级等同于它所属进程的优先级。一个线程的优先级是相对于其所属的进程的优先级而言的。可以通过调用ACE_Thread::setprio函数改变线程的相对优先级,该函数的调用方式如下: ACE_Thread::setprio(threadHandle,ACE_DEFAULT_THREAD_PRIORITY)
4.挂起及恢复线程
挂起线程可以通过来实现,它能暂停一个线程的执行,其调用方式如下ACE_Thread::suspend(threadHandle)。 相应的,可以通过ACE_Thread::resume(threadHandle)恢复被挂起的线程的执行。
5.等待线程结束
在主函数中调用ACE_Thread::join(threadHandle)可阻塞主函数,直道线程结束才能继续执行。
6.停止线程
在主函数中调用ACE_Thread::cancel (threadHandle)可停止线程的执行(在Unix底下可以,而在windows下好像不起作用,有待检验)。
三.程序示例
下面例子演示了如何用ace创建一个线程。
#include "ace/Thread.h"
#include "ace/Synch.h"
#pragma comment(lib,"ACEd.lib")
#include
usingnamespace std;
void* worker(void *arg)
{
for(int i=0;ideactivate(); ++loop; } if(loop == 2) { ACE_OS::sleep(2); //将消息队列的状态设置成ACTIVATED //消息又可以使用了 mq->activate(); ++loop; } if(loop == 3) { ACE_OS::sleep(10); //消费两个消息之后,数据量就小于5了,低于低水位将唤醒生产者 ACE_Message_Block *mb; mq->dequeue_head (mb); mq->dequeue_head (mb); ACE_DEBUG((LM_DEBUG, "(%P : %t) consumer wake up producer!!\n")); ++loop; } } return NULL; } int main(int argc,char* argv[]) { mq = ACE_Message_Queue_Factory::create_static_message_queue(); int priority; //使用随机数作为消息的优先级 //数字越高,优先级越高 priority = ACE_OS::rand() % 100; mb1 = new ACE_Message_Block(S1,sizeof S1, priority); priority = ACE_OS::rand() % 100; mb2 = new ACE_Message_Block(S2,sizeof S2, priority); priority = ACE_OS::rand() % 100; mb3 = new ACE_Message_Block(S3,sizeof S3, priority); priority = ACE_OS::rand() % 100; mb4 = new ACE_Message_Block(S4,sizeof S4, priority); //将消息压入队列中,enqueue_prio根据消息的优先级将消息放到适当的位置上 //enqueue_head只是简单地将数据存入队列中,而不考虑消息的优先级 //使用enqueue_prio压入消息后,可以简单通过dequeue_head和dequeue_tail //分别按优先级从高到低和从低到高取消息 //如果使用enqueue_head和enqueue_tail压入消息 //则需要通过dequeue_prio来按照消息的优先级依次将消息出队列 //没有必要既使用enqueue_prio压入消息,又实用dequeue_prio来取消息 mq->enqueue_prio (mb1); mq->enqueue_prio (mb2); mq->enqueue_prio (mb3); mq->enqueue_prio (mb4); //输出静态消息队列的相关信息 //高低水位默认值均为16384 ACE_DEBUG((LM_DEBUG, "count : %d, bytes : %d, length : %d, high_water_mark : %d, low_water_mark : %d, status : %d\n", mq->message_count(), mq->message_bytes(), mq->message_length(), mq->high_water_mark(), mq->low_water_mark(), mq->state())); ACE_Message_Block *mb; //使用next遍历消息,遍历的顺序为高优先级到底优先级 ACE_DEBUG((LM_DEBUG, "===========next=============\n")); //peek一下,并不弹出消息,类似Windows的PeekMessage mq->peek_dequeue_head(mb); do { ACE_DEBUG((LM_DEBUG, "message: %s, priority: %d\n", mb->rd_ptr(), mb->msg_priority())); }while(mb = mb->next()); //使用迭代器遍历消息队列,遍历的顺序为高优先级到底优先级 ACE_DEBUG((LM_DEBUG, "=========iterator=============\n")); ACE_Message_Queue::ITERATOR iterator (*mq); for (ACE_Message_Block *entry = 0; iterator.next (entry) != 0; iterator.advance ()) { ACE_DEBUG((LM_DEBUG, "message: %s, priority: %d\n", entry->rd_ptr(), entry->msg_priority())); } ACE_DEBUG((LM_DEBUG, "============dequeue_head==========\n")); while(mq->dequeue_head (mb) != -1) { ACE_DEBUG((LM_DEBUG, "message: %s, priority: %d\n", mb->rd_ptr(), mb->msg_priority())); //这里如果不判断的话,消息队列空时会导致主线程被阻塞 if(mq->is_empty()) break; } ACE_DEBUG((LM_DEBUG, "\n\n")); //测试高低水位和队列的state使用,进行测试之前mq队列已空/// //产生一个生产者线程 ACE_Thread_Manager::instance()->spawn_n ( 1, (ACE_THR_FUNC) produce ); 产生两个消费者线程 ACE_Thread_Manager::instance()->spawn_n ( 1, (ACE_THR_FUNC) consume ); //挂起主线程 ACE_Thread_Manager::instance()->wait(); return 0; }
ACE中TCP通信
Tcp通信过程一般为如下步骤:
1. 服务器绑定端口,等待客户端连接。
2. 客户端通过服务器的ip和服务器绑定的端口连接服务器。
3. 服务器和客户端通过网络建立一条数据通路,通过这条数据通路进行数据交互。
常用API:
1. ACE_INET_Addr类。
ACE"地址"类ACE_Addr的子类,表示TCP/IP和UDP/IP的地址。它通常包含机器的ip和端口信息,通过它可以定位到所通信的进程。
定义方式: ACE_INET_Addr addInfo(3000,"192.168.1.100"); 常用方法:
1. get_host_name 获取主机名
2. get_ip_address 获取ip地址
3. get_port_number 获取端口号
2. ACE_SOCK_Acceptor类。
服务期端使用,用于绑定端口和被动地接受连接。 常用方法:
1. open 绑定端口
2. accept建立和客户段的连接
3.ACE_SOCK_Connector类。
客户端使用,用于主动的建立和服务器的连接。 常用方法:
1. connect() 建立和服务期的连接。
4. ACE_SOCK_Stream类。
客户端和服务器都使用,表示客户段和服务器之间的数据通路。 常用方法:
1. send () 发送数据
2. recv () 接收数据
3. close() 关闭连接(实际上就是断开了socket连接)。
代码示例:
下面例子演示了如何如何用ACE创建TCP通信的Server端。
#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Stream.h"
#include "ace/INET_Addr.h"
#include "ace/OS.h"
#include
#include
usingnamespace std;
int main(int argc,char *argv[])
{
ACE_INET_Addr port_to_listen(3000); //绑定的端口
ACE_SOCK_Acceptor acceptor;
if (acceptor.open (port_to_listen, 1) == -1) //绑定端口
{
cout
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?