图解VC++6.0和ACE 5.4 开发入门
一 工具和下载
工具和环境:
Win7, VC++6, ACE5.4
可在Win7下运行的VC6下载:
http://blog.csdn.net/bcbobo21cn/article/details/44200205
ACE安装包和本文demo代码下载:
http://pan.baidu.com/s/1kUUOOlh
注意有两个ace安装包,5.4是dsw的工程,6.3是sln的工程
二 安装环境
下载ace54,解压;
在vc6.0中打开ace源码;
2个工程;网上资料有说3个工程;
在工程中双击config.h,询问是否要创建,单击是;
输入
#include "ace/config-win32.h"
看下lib目录,现在是空的;
在工程设置中作如下设置,
开始build;一堆cpp文件一个个被编译;
编译成功;
但是查看lib目录,空的;啥也没有;
生成了dll, 不在lib目录,并且没有生成lib文件;
重新修改工程设置如下图;
要改两处;
..\lib\aced.dll
/out:"..\lib\aced.dll" /implib:"..\lib\aced.lib"
这个和网上别的教程有所区别;大家可以参考之;
再bulid,好了,dll和lib都出来了;此框架就一个dll;
三 控制台demo
新建控制台工程;
新建一个空工程;
添加cpp源文件;
代码见后;
再新建客户端工程;前面那个是服务器端项目;
预处理器和附加包含路径;如下图;加入这个;
ACE_AS_STATIC_LIBS
添加lib库和附加库路径;
服务器端和客户端的代码;
#include "ace/Addr.cpp"
#include "ace/Time_Value.cpp"
#include "ace/Message_Queue.h"
#include "ace/Asynch_IO.h"
#include "ace/OS.h"
#include "ace/Proactor.h"
#include "ace/Asynch_Acceptor.h"
#include "ace/SOCK_SEQPACK_Association.h"
class Proactive_Service : public ACE_Service_Handler
{
public:
~Proactive_Service ()
{
if (this->handle () != ACE_INVALID_HANDLE)
ACE_OS::closesocket (this->handle ());
}
/******************************************************/
/*每当客户端连接到服务器就会调用此函数 */
/******************************************************/
virtual void open (ACE_HANDLE h, ACE_Message_Block&)
{
this->handle (h);
//打开与客户端的读取流
if (this->reader_.open (*this) != 0 )
{
delete this;
return;
}
//开打与客户端的写出流
if (this->writer_.open (*this) != 0 )
{
delete this;
return;
}
ACE_Message_Block *mb = new ACE_Message_Block(buffer,1024);
if (this->reader_.read (*mb, mb->space ()) != 0)
{
ACE_OS::printf("Begin read fail/n");
delete this;
return;
}
return;
}
//异步读完成后会调用此函数
virtual void handle_read_stream
(const ACE_Asynch_Read_Stream::Result &result){
ACE_Message_Block &mb = result.message_block ();
//如果读取失败说明客户端关闭,在这里删除客户端连接资源
if (!result.success () || result.bytes_transferred () == 0)
{
mb.release ();
delete this;
return;
}
mb.copy(""); //为字符串添加结束标记'/0'
ACE_OS::printf("rev:/t%s/n",mb.rd_ptr());
mb.release();
ACE_Message_Block *mbb = new ACE_Message_Block(100);
mbb->copy("daye say hello");
if (this->writer_.write(*mbb,mbb->length()) !=0)
{
delete this;
return;
}
ACE_Message_Block *nmb = new ACE_Message_Block(buffer,1024);
if (this->reader_.read (*nmb, nmb->space ()) != 0)
return;
}
//异步写完成后会调用此函数
virtual void handle_write_dgram
(const ACE_Asynch_Write_Stream::Result &result)
{
ACE_Message_Block &mb = result.message_block ();
mb.release();
return;
}
private:
ACE_Asynch_Read_Stream reader_;
ACE_Asynch_Write_Stream writer_;
char buffer[1024];
};
int main(int argc, char *argv[])
{
ACE::init();//初始化dll资源
int port=20002;//指定监听端口
ACE_Asynch_Acceptor<Proactive_Service> acceptor;
//在指定的端口上进行监听
if (acceptor.open (ACE_INET_Addr (port)) == -1)
return -1;
//开始等待客户端的连接
ACE_Proactor::instance ()->proactor_run_event_loop();
ACE::fini();//释放dll资源
return 0;
}
========
#include "ace/SOCK_Connector.h"
#include "ace/OS_NS_string.h"
#include "ace/OS_NS_stdio.h"
#include "ace/Addr.cpp"
#include "ace/Time_Value.cpp"
#include "ace/Message_Queue.h"
#include "ace/Asynch_IO.h"
#include "ace/OS.h"
#include "ace/Proactor.h"
#include "ace/Asynch_Connector.h"
class Proactive_Client : public ACE_Service_Handler
{
public:
~Proactive_Client ()
{
if (this->handle () != ACE_INVALID_HANDLE)
ACE_OS::closesocket (this->handle ());
}
virtual void open (ACE_HANDLE h, ACE_Message_Block&)
{
this->handle (h);
if (this->reader_.open (*this) != 0 )
{
delete this;
return;
}
if (this->writer_.open (*this) != 0 )
{
delete this;
return;
}
ACE_Message_Block *mb = new ACE_Message_Block(buffer,1024);
if (this->reader_.read (*mb, mb->space ()) != 0)
{
delete this;
return;
}
ACE_OS::printf("connceted/n");
time_t now = ACE_OS::gettimeofday().sec();
char *time = ctime(&now); //获取当前时间的字符串格式
ACE_Message_Block *mbb = new ACE_Message_Block(100);
mbb->copy(time);
if (this->writer_.write(*mbb,mbb->length()) !=0)
{
delete this;
return;
}
return;
}
//异步读完成后会调用此函数
virtual void handle_read_stream
(const ACE_Asynch_Read_Stream::Result &result)
{
ACE_Message_Block &mb = result.message_block ();
if (!result.success () || result.bytes_transferred () == 0)
{
mb.release ();
delete this;
return;
}
mb.copy(""); //为字符串添加结束标记'/0'
ACE_OS::printf("rev:/t%s/n",mb.rd_ptr());
mb.release();
ACE_Message_Block *nmb = new ACE_Message_Block(buffer,1024);
if (this->reader_.read (*nmb, nmb->space ()) != 0)
return;
}
//异步写完成后会调用此函数
virtual void handle_write_dgram
(const ACE_Asynch_Write_Stream::Result &result)
{
ACE_Message_Block &mb = result.message_block ();
mb.release();
return;
}
private:
ACE_Asynch_Write_Stream writer_;
ACE_Asynch_Read_Stream reader_;
char buffer[1024];
};
int main(int argc, char *argv[])
{
ACE::init();
ACE_INET_Addr addr(20002,"127.0.0.1");//服务器地址和端口
ACE_Asynch_Connector<Proactive_Client> connector;
connector.open();
if (connector.connect(addr) == -1)
return -1;
ACE_Proactor::instance()->proactor_run_event_loop();
ACE::fini();
return 0;
}
运行下;
找不到dll,把前面生成的aced.dll直接拷贝到此工程生成的exe文件的同一目录下;再运行;看到客户端和服务器端通信了;不过此代码只能通信一次;一锤子而已;
要搞成项目需要自己搞定;
四 窗口模式的通信
新建一个MFC客户端;
做一个如下的界面;
在项目中加入四个文件;
========
RecvTask.h
#ifndef RECVTASK_H
#define RECVTASK_H
#include "ace/Task.h"
#include "ace/OS.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Connector.h"
#define MSG_LEN_BYTES 128
#define TIME_OUT_VALUE 1000000
class RecvTask: public ACE_Task<ACE_MT_SYNCH>
{
public:
RecvTask();
int open(void* p);
int close(u_long);
//接收服务器的信息
int svc(void);
};
#endif
RecvTask.cpp
#include "stdafx.h"
#include "RecvTask.h"
#include "ace/ACE.h"
#include "ace/OS.h"
#include "ace/SOCK_Connector.h"
#include "ace/INET_Addr.h"
#include "ace/Task.h"
#include "Client.h"
int RecvTask::svc(void)
{
while(true)
{
Client::getInstance()->recvMessage();
ACE_OS::sleep(ACE_Time_Value( 0, 5000 ));
}
}
int RecvTask::open(void* p)
{
activate();
return 0;
}
int RecvTask::close(u_long)
{
return 0;
}
RecvTask::RecvTask(){}
Client.h
#ifndef CLIENR_H
#define CLIENR_H
#include "stdafx.h"
#include "ace/ACE.h"
#include "ace/OS.h"
#include "ace/SOCK_Connector.h"
#include "ace/INET_Addr.h"
#include "ace/Task.h"
#include "RecvTask.h"
class Client
{
public:
~Client();
/***************************************************************/
/* 根据ip地址和端口号,连接服务器,如果连接成功返回0,失败返回-1 */
/***************************************************************/
int connect(int port,char * localhost);
/***************************************************************/
/* 获取客户端实例 */
/***************************************************************/
static Client * getInstance();
/***************************************************************/
/* 给服务器发送数据信息,返回发的字节数 */
/***************************************************************/
int sendMessage(char * msg);
/**************************************************************/
/* 关闭与远程服务器的连接,成功返回0,失败返回-1 */
/**************************************************************/
int close();
void recvMessage();
private:
Client();
ACE_SOCK_Connector connector;
ACE_Thread_Mutex mutex;
RecvTask * recvTask;
static Client * instance;
static BOOL hasInstance;
ACE_SOCK_Stream stream;
};
#endif
Client.cpp
#include "stdafx.h"
#include "RecvTask.h"
#include "ace/ACE.h"
#include "ace/OS.h"
#include "ace/SOCK_Connector.h"
#include "ace/INET_Addr.h"
#include "ace/Task.h"
#include "Client.h"
#include "ace/OS_NS_string.h"
Client * Client::instance=NULL;
BOOL Client::hasInstance=false;
Client::~Client()
{
if (recvTask!=NULL)
{
delete recvTask;
recvTask=NULL;
}
}
Client * Client::getInstance()
{
if (!hasInstance)
{
instance= new Client();
hasInstance=true;
}
return instance;
}
int Client::connect(int port,char * localhost)
{
recvTask = new RecvTask();
//stream = new ACE_SOCK_Stream();
ACE_INET_Addr remote_addr(port,localhost);
int result=connector.connect(stream, remote_addr);
if (result==0)
{
recvTask->open(0);
}else{
recvTask->close(0);
delete recvTask;
}
return result;
}
int Client::sendMessage(char * msg)
{
return stream.send_n(msg,ACE_OS::strlen(msg));
//return recvTask->getStream().send_n(msg,ACE_OS::strlen(msg));
}
void Client::recvMessage()
{
size_t recv_len;
char sLen[MSG_LEN_BYTES + 1];
ACE_Time_Value t(0, TIME_OUT_VALUE / 2);
stream.recv_n(sLen, MSG_LEN_BYTES, &t, &recv_len);
if (recv_len!=0)
{
sLen[recv_len]=0;
AfxMessageBox(sLen);
}
}
int Client::close()
{
recvTask->close(0);
stream.close();
return 0;
}
Client::Client()
{
}
========
为编辑框添加一个成员变量;
三个按钮代码;
连接
ACE::init();
if(Client::getInstance()->connect(20002,"127.0.0.1")==0)
{
AfxMessageBox("连接成功");
}else{
AfxMessageBox("连接失败");
}
添加到对话框实现文件头部
#include "ace/Addr.cpp"
#include "Client.h"
发送
UpdateData(true);
Client::getInstance()->sendMessage(m_send.GetBuffer(m_send.GetLength()));
“退出”按钮的代码
Client::getInstance()->close();
ACE::fini();
CDialog::OnCancel();
运行结果:
五 一个错误的解决-C2061、C2091、C2653、C2065
构建时出现下述错误,
Compiling...
WinClientDlg.cpp
c:\program files (x86)\microsoft visual studio\vc98\include\new(35) : error C2061: syntax error : identifier 'THIS_FILE'
c:\program files (x86)\microsoft visual studio\vc98\include\new(35) : error C2091: function returns function
......
Generating Code...
Compiling...
WinClient.cpp
Generating Code...
执行 cl.exe 时出错.
把
#include "ace/Addr.cpp"
#include "Client.h"
移动到对话框实现文件的最前面,再编译;
又出现,
Compiling...
WinClientDlg.cpp
C:\acedemo\demo1\WinClient\WinClientDlg.cpp(180) : error C2653: 'ACE' : is not a class or namespace name
C:\acedemo\demo1\WinClient\WinClientDlg.cpp(180) : error C2065: 'init' : undeclared identifier
......
C:\acedemo\demo1\WinClient\WinClientDlg.cpp(200) : error C2065: 'fini' : undeclared identifier
执行 cl.exe 时出错.
此时的头文件包含代码如下;
#include "ace/Addr.cpp"
#include "Client.h"
#include "stdafx.h"
#include "WinClient.h"
#include "WinClientDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
把文件包含代码改为如下;
#include "stdafx.h"
#include "WinClient.h"
#include "WinClientDlg.h"
#include "ace/Addr.cpp"
#include "Client.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
再构建;搞定;
以下是网上关于此错误的一段论述:
VC6提示 error C2061: syntax error : identifier 'THIS_FILE' 错误的解决办法
今天在编译一段以前写的代码时候,遇到了这样的错误
--------------------Configuration: AppSharePlugin - Win32 Debug--------------------
Compiling...
AppSharePluginModule.cpp
d:\program files\microsoft visual studio\vc98\include\new(35) : error C2061: syntax error : identifier 'THIS_FILE'
......
d:\program files\microsoft visual studio\vc98\include\memory(16) : see declaration of 'new'
d:\program files\microsoft visual studio\vc98\include\memory(17) : error C2809: 'operator new' has no formal parameters
......
Error executing cl.exe.
AppSharePlugin.dll - 17 error(s), 0 warning(s)
双击第一个错误,居然跳转到了完全陌生的系统头文件
\microsoft visual studio\vc98\include\new(35)
中。开始怀疑是新老SDK混合引起的冲突,修改了几下参数,无果,只好向GOOGLE请教了。搜索一番之后很快明白了问题的所在,引起错误代码是这样的
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
//blah blah, lots of codes here
//
#include <vector>
using namespace std;
由于new已经被宏定义为DEBUG_NEW,所以在<vector>中包含的<new>中如下代码就出问题了:
void *__cdecl operator new(size_t) _THROW1(std::bad_alloc);
解决方法也很简单,把
#include <vector>
using namespace std;
两行代码,移到最前面即可!
六 安装和工程设置的文字描述
1.解压缩ace源代码包,假设在D:/ACE_wrappers
2.使用vc打开D:/ACE_wrappers/ace/ace.dsw
3.工作区上有三个工程,在ACE工程的头文件中找到config.h
4.双击打开这个文件,会有提示这个文件不存在是否创建,点是
5.在config.h中写入#include "ace/config-win32.h"表示windos 32位操作系统
6.在ACE工程上右键Settings... 选择c/c++ 在Caterory中选择 Code Generation 然后在 Use run-time library 中选择 Debug Multithreaded DLL
7.在ACE工程上右键 build(selection only)
8.编译后会在D:/ACE_wrappers/lib 目录中生成ACEd.lib ACEd.dll ACEd.exp ACEd.pdb等文件
9.D:/ACE_wrappers/ ACE-INSTALL.html有完整具体的安装指南
配置ace的工程
在使用到ace的工程中都要进行的一些设置
1. 选择Project->Settings...
2. 选择c/c++ 在Caterory中选择 Code Generation 然后在 Use run-time library 中选择 Debug Multithreaded DLL
3. 在Caterory中选择Preprocessor 在Preprocessor definitions 中添加ACE_AS_STATIC_LIBS 使用逗号与前面的内容隔开 在Additional include directories 中写入ACE的根目录D:/ACE_wrappers
4. 选择 Link 在Caterory中选择Input 在Additional library path 中加入D:/ACE_wrappers/lib 在Object/library modules 后追加aced.lib 用空格与前面的内容隔开
5. 设置完整以后重启vc
图解VC++6.0和ACE 5.4 开发入门相关推荐
- 计算机二级软件VC++6.0下载地址
计算机二级软件VC++6.0介绍: 适合所有参加全国计算机等级考试的童鞋们--见图如下: 下载地址:(以下两者任选其一即可) (1).计算机二级软件VC++6.0(16.35MB) (2).计算机二级 ...
- 图解VC++2012编译安装GDAL1.11.0和入门例子
相关下载 http://pan.baidu.com/s/1o7OEMc6 gdal1.rar - 入门例子 GDAL书籍代码及数据.rar gdal1110.zip - 下载的源码 GDAL.rar ...
- VC++ 6.0的小花招
Visual Studio系列中产品中,Visual Studio 6.0是最经典的一个版本,虽然后来有Visual Studio .NET 2003,以及2005,也确实添加了很多让我觉得激动的特性 ...
- 使用VC++6.0创建MFC对话框程序
使用VC++6.0创建MFC对话框程序
- vc 6.0的安装问题
vc 6.0安装只需要 下载好压缩包 解压后,在E:\vc++6.0\Common\MSDev98\Bin目录下找到MSDEV然后随意改个名字叫MSDEV1然后点击它右键找到属性,找到兼容性选择 修改 ...
- vc 6.0常见编译错误及改正方法
最常见VC++6.0编译错误信息集合 1.fatal error C1010: unexpected end of file while looking for precompiled header ...
- VC++ 6.0下OpengGL配置以及glut配置
转自:http://blog.sina.com.cn/s/blog_5f0cf7bd0100c9oa.html OpenGL官方网站(英文) http://www.opengl.org 下面我将对Wi ...
- vc++ 6.0对话框上无法显示中文(乱码)
是英文版的vc++,建立mfc向导时无法选择中文,到对话框里面改成中文还是乱码,怎么版啊 问题补充: 一般对话框是可以的,就是那个CPropertyPage 不可以对话框资源选成中文以后要ReBuil ...
- Basler相机Pylon4配置VC++6.0
以前都是用到大恒相机,今天要配置两个Basler相机使用,记录一下过程 配置:VC++6.0,Basler相机 1,点击工程->设置 2,C/C++,Y分类选择Preprocessor 3,包含 ...
最新文章
- 从客户端(CourseIssueContent=P财务审计师岗位认证招生简章BR...)中检测到有潜在危险的 Request.Form 值。...
- 分布式系统:CAP 理论的前世今生
- ubuntu的mysql教程 pdf_Ubuntu上的MySQL字符集设置技巧
- Spring Boot学习总结(8)——SpringBoot Common application properties(application.properties)详解
- Zookeeper配置参数与节点值的解读
- k进制正整数的对k-1取余与按位取余
- 怎样访问远程服务器文件夹,远程访问服务器文件夹
- PWA 应用列表及常用工具
- 小暑海报文案|小暑海报设计图片素材
- netbeans java桌面应用程序_java – 使用Netbean的桌面应用程序的状态栏
- 【系】微信小程序云开发实战坚果商城-云开发之分类数据实现
- 滑膜间充质干细胞复合壳聚糖水凝胶/角蛋白壳聚糖水凝胶复合材料/壳聚糖/海藻酸纳复合水凝胶的制备
- 新面貌,新征程—读《新程序员》有感
- WBS(工作分解结构)
- Mikrotik ROS软路由配置PCC负载均衡实现双宽带叠加
- 哪些东西做引流产品比较好?哪些商品是每天比较受欢迎的?
- 网站导航怎么设置利于网站SEO优化
- Java实现 蓝桥杯 算法训练 Cowboys
- postgresql Count estimate
- LoRa + 蓝牙室内场馆定位技术全面解析
热门文章
- 正态分布||方差、均值的概念
- Sculpture ACM/ICPC NWERC 2008 离散化
- 7.1 matlab符号对象(符号对象的建立和四则运算)
- matlab 寻找二进制图像边缘
- mysql第一二章笔记_MYSQL必知必会读书笔记 第一章(基础)
- java mybatis拦截配置_SpringMvc拦截器配置_JavaEE框架(Maven+SpringMvc+Spring+MyBatis)全程实战教程_Java视频-51CTO学院...
- alpinestars与丹尼斯_骑行靴|丹尼斯VS A星心得分享,它和普通鞋子不同之处竟在这里!...
- XML和实体类之间相互转换(序列化和反序列化)
- BZOJ1406: [AHOI2007]密码箱 数论
- Median of Two Sorted Arrays