图解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_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 怎么做工程设置,最好图解

C++班级同学信息管理(VC++6.0)

vc++6.0和VC2017区别

初学c++,vc++6.0必备!

图解VC++ opengl环境配置和几个入门样例

visual stdio2005 如何像vc++6.0一样编译和调试啊