图解VC++6.0和ACE 5.4 开发入门
Posted bcbobo21cn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图解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_wrappers2.使用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 开发入门的主要内容,如果未能解决你的问题,请参考以下文章