图解VC++6.0和ACE 5.4 开发入门
一 工具和下載
工具和環(huán)境:
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的工程
二 安裝環(huán)境
下載ace54,解壓;
在vc6.0中打開ace源碼;
2個工程;網(wǎng)上資料有說3個工程;
在工程中雙擊config.h,詢問是否要創(chuàng)建,單擊是;
輸入
#include "ace/config-win32.h"
看下lib目錄,現(xiàn)在是空的;
在工程設(shè)置中作如下設(shè)置,
開始build;一堆cpp文件一個個被編譯;
編譯成功;
但是查看lib目錄,空的;啥也沒有;
生成了dll, 不在lib目錄,并且沒有生成lib文件;
重新修改工程設(shè)置如下圖;
要改兩處;
..\lib\aced.dll
/out:"..\lib\aced.dll" /implib:"..\lib\aced.lib"?
這個和網(wǎng)上別的教程有所區(qū)別;大家可以參考之;
再bulid,好了,dll和lib都出來了;此框架就一個dll;
三 控制臺demo
新建控制臺工程;
新建一個空工程;
添加cpp源文件;
代碼見后;
再新建客戶端工程;前面那個是服務(wù)器端項目;
預(yù)處理器和附加包含路徑;如下圖;加入這個;
ACE_AS_STATIC_LIBS
添加lib庫和附加庫路徑;
服務(wù)器端和客戶端的代碼;
#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 ()); ?
? ? } ?
? ? /******************************************************/ ?
/*每當(dāng)客戶端連接到服務(wù)器就會調(diào)用此函數(shù) ? ? ? ? ? ? ? ? */ ?
? ? /******************************************************/ ?
? ? 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; ?
? ? } ?
? ? ??
? ? //異步讀完成后會調(diào)用此函數(shù) ?
? ? virtual void handle_read_stream ?
? ? ? ? (const ACE_Asynch_Read_Stream::Result &result){ ?
? ? ? ? ACE_Message_Block &mb = result.message_block (); ?
? ? ? ? //如果讀取失敗說明客戶端關(guān)閉,在這里刪除客戶端連接資源 ?
? ? ? ? if (!result.success () || result.bytes_transferred () == 0) ?
? ? ? ? { ?
? ? ? ? ? ? mb.release (); ?
? ? ? ? ? ? delete this; ?
? ? ? ? ? ? return; ?
? ? ? ? } ?
? ? ? ? ??
? ? ? ? mb.copy(""); ? ?//為字符串添加結(jié)束標(biāo)記'/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; ?
? ? } ?
??
? ? //異步寫完成后會調(diào)用此函數(shù) ?
? ? 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;//指定監(jiān)聽端口 ?
? ? ACE_Asynch_Acceptor<Proactive_Service> acceptor; ?
? ? ??
? ? //在指定的端口上進(jìn)行監(jiān)聽 ?
? ? 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); ? ? ? ?//獲取當(dāng)前時間的字符串格式 ?
? ? ? ? ACE_Message_Block *mbb = new ACE_Message_Block(100); ?
? ? ? ? mbb->copy(time); ?
? ? ? ? ??
? ? ? ? if (this->writer_.write(*mbb,mbb->length()) !=0) ?
? ? ? ? { ?
? ? ? ? ? ? delete this; ?
? ? ? ? ? ? return; ?
? ? ? ? } ?
? ? ??
? ? ? ? return; ?
? ? } ?
? ? ??
? ? //異步讀完成后會調(diào)用此函數(shù) ?
? ? 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(""); ? ?//為字符串添加結(jié)束標(biāo)記'/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; ?
? ? } ?
? ? ??
? ? //異步寫完成后會調(diào)用此函數(shù) ?
? ? 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");//服務(wù)器地址和端口 ?
? ? 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文件的同一目錄下;再運行;看到客戶端和服務(wù)器端通信了;不過此代碼只能通信一次;一錘子而已;
要搞成項目需要自己搞定;
四 窗口模式的通信
新建一個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); ?
? ? //接收服務(wù)器的信息 ?
? ? 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(); ?
? ? /***************************************************************/ ?
? ? /* 根據(jù)ip地址和端口號,連接服務(wù)器,如果連接成功返回0,失敗返回-1 */ ?
? ? /***************************************************************/ ?
??
? ? int connect(int port,char * localhost); ?
??
? ? /***************************************************************/ ?
? ? /* 獲取客戶端實例 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*/ ?
? ? /***************************************************************/ ?
??
? ? static Client * getInstance(); ?
??
? ? /***************************************************************/ ?
? ? /* 給服務(wù)器發(fā)送數(shù)據(jù)信息,返回發(fā)的字節(jié)數(shù) ? ? ? ? ? ? ? ? ? ? ? ?*/ ?
? ? /***************************************************************/ ?
? ? int sendMessage(char * msg); ?
? ? ??
? ? /**************************************************************/ ?
? ? /* 關(guān)閉與遠(yuǎn)程服務(wù)器的連接,成功返回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("連接失敗"); ?
? ? ? ? ??
? ? } ?
添加到對話框?qū)崿F(xiàn)文件頭部
#include "ace/Addr.cpp"
#include "Client.h"
發(fā)送
UpdateData(true);
Client::getInstance()->sendMessage(m_send.GetBuffer(m_send.GetLength()));
?
“退出”按鈕的代碼
Client::getInstance()->close(); ?
ACE::fini(); ?
CDialog::OnCancel(); ?
運行結(jié)果:
五 一個錯誤的解決-C2061、C2091、C2653、C2065
構(gòu)建時出現(xiàn)下述錯誤,
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...
執(zhí)行 cl.exe 時出錯.
把
#include "ace/Addr.cpp"
#include "Client.h"
移動到對話框?qū)崿F(xiàn)文件的最前面,再編譯;
又出現(xiàn),
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
執(zhí)行 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
再構(gòu)建;搞定;
以下是網(wǎng)上關(guān)于此錯誤的一段論述:
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)
?
雙擊第一個錯誤,居然跳轉(zhuǎn)到了完全陌生的系統(tǒng)頭文件
\microsoft visual studio\vc98\include\new(35)
中。開始懷疑是新老SDK混合引起的沖突,修改了幾下參數(shù),無果,只好向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已經(jīng)被宏定義為DEBUG_NEW,所以在<vector>中包含的<new>中如下代碼就出問題了:
void *__cdecl operator new(size_t) _THROW1(std::bad_alloc);
解決方法也很簡單,把
#include <vector>
using namespace std;
兩行代碼,移到最前面即可!
六?安裝和工程設(shè)置的文字描述
1.解壓縮ace源代碼包,假設(shè)在D:/ACE_wrappers2.使用vc打開D:/ACE_wrappers/ace/ace.dsw
3.工作區(qū)上有三個工程,在ACE工程的頭文件中找到config.h
4.雙擊打開這個文件,會有提示這個文件不存在是否創(chuàng)建,點是
5.在config.h中寫入#include "ace/config-win32.h"表示windos 32位操作系統(tǒng)
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的工程中都要進(jìn)行的一些設(shè)置
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 使用逗號與前面的內(nèi)容隔開 在Additional include directories 中寫入ACE的根目錄D:/ACE_wrappers
4. ? ?選擇 Link 在Caterory中選擇Input 在Additional library path 中加入D:/ACE_wrappers/lib 在Object/library modules 后追加aced.lib 用空格與前面的內(nèi)容隔開
5. ? ?設(shè)置完整以后重啟vc
總結(jié)
以上是生活随笔為你收集整理的图解VC++6.0和ACE 5.4 开发入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux块设备驱动总结
- 下一篇: VC ActiveX 控件 开发总结