使用 DCOM 进行客户端/服务器连接,匿名访问






4.17/5 (10投票s)
2005 年 2 月 9 日
2分钟阅读

111216

2976
快速实现使用 DCOM 的客户端/服务器连接。
引言
本文将解释如何使用 DCOM 实现快速的客户端/服务器连接。
使用代码
本文包含两部分:
- 服务器端实现
- 客户端实现
让我们从服务器端实现开始
- 使用 Visual Studio 启动“新建 ATL COM 向导项目”。
- 将其命名为 TestServer。
- 选择服务器类型:服务。
- 插入新的 ATL 对象:类别-对象,对象-简单对象。
- 将接口命名为
IHello
。 - 添加方法
Beep()
。
现在,我们需要关闭 DCOM 服务器的身份验证。从工作区窗口打开 TestServer.rgs,并在 'TestServer.EXE' 之前添加以下行:
{ val AccessPermission = b '01000480300000004c000000000000001 400000002001c000100000000021400010000000101000000000001000000000 105000000000005150000007ceb240dfa4f0c2ff89fb474f2030000010500000 0000005150000007ceb240dfa4f0c2ff89fb47401020000' val LaunchPermission = b '01000480300000004c000000000000001 400000002001c000100000000021400010000000101000000000001000000000 105000000000005150000007ceb240dfa4f0c2ff89fb474f2030000010500000 0000005150000007ceb240dfa4f0c2ff89fb47401020000' }
打开 testMonitor.cpp,找到 Run()
函数,并使其如下所示:
void CServiceModule::Run() { _Module.dwThreadID = GetCurrentThreadId(); //This means that calls come in on a random RPC thread HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); // This provides a NULL DACL which will allow access to everyone. hr = CoInitializeSecurity( 0, -1, 0, 0, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, 0, 0, 0 ); hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE); ..............
最后,将以下行添加到 Beep()
方法,服务器端就准备好了!!!
MessageBeep(MB_ICONEXCLAMATION);
现在,让我们实现客户端
- 启动“新建 MFC 应用程序向导,基于对话框,命名为 TestClient”。
- 插入资源,自定义,并将其命名为 TYPELIB。
- TYPELIB 资源的 ID 必须为 1。
- 打开 TYPELIB 资源的属性页,并将路径指定为文件 TestServer.tlb。
- 将
#import "..//TestServer/testserver.tlb" no_namespace
行添加到 stdafx.h。 - 将
include
s for Afxctl.h、objbase.h 和 initguid.h 添加到 stdafx.h。 - 将
_WIN32_DCOM
添加到预处理器定义。
现在,我们需要添加实际的连接代码。将以下 Connect()
函数添加到您的应用程序类:
IIHello* CTestClientApp::Connect(CString& strIPAddress, CString& strError) { // register type library CLSID libid; CLSIDFromString (L"{55259785-1985-4DCB-B4BA-FCB7F968DFA4}", &libid); if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), libid)) { AfxMessageBox("Failed to register server's type library"); return NULL; } CLSID clsid; const IID IID_IHELLO = {0xFB57F08C,0x0F91,0x4046, {0x8E,0xF1,0x05,0xD8,0x90,0x4C,0x66,0xF0}}; MULTI_QI mqi = { &IID_IHELLO, 0, 0 }; CLSIDFromString (L"{C7B7C24F-5B72-49D0-962B-FFD650BFFA2B}", &clsid); CoInitialize(0); COAUTHINFO cai = { RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, 0, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE}; COSERVERINFO csi = { 0, strIPAddress.AllocSysString(), &cai, 0 }; HRESULT hr = CoCreateInstanceEx(clsid, NULL, CLSCTX_REMOTE_SERVER, &csi, 1, &mqi); if (FAILED(hr)) { TCHAR szError[1024]; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), szError, 1024, NULL); strError = szError; return FALSE; } return (IIHello*)(mqi.pItf); }
从上面的代码可以看出,需要三个 GUID:LIBID
、CLASSID
和 ITERFACEID
。它们都必须从 testserver.idl 中获取。我们的连接代码示例有点硬编码,但它允许在任何机器上运行客户端而无需任何注册。服务器必须在使用前注册。由于这是一个 DCOM 服务器,它可以注册为服务或本地服务器。要将服务器注册为服务,请键入:
testserver /Service
要将服务器注册为本地服务器,请键入:
testserver /RegServer
最后,让我们在远程服务器上执行 Beep()
方法。为此,只需为 Beep 按钮添加一个处理程序即可。
void CTestClientDlg::OnButtonBeep()
{
((CTestClientApp*)AfxGetApp())->m_pHello->Beep();
}
希望这不会很枯燥,但对您有所帮助 :-)
历史
- 2005/02/06 - 初始文档创建。