65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.17/5 (10投票s)

2005 年 2 月 9 日

2分钟阅读

viewsIcon

111216

downloadIcon

2976

快速实现使用 DCOM 的客户端/服务器连接。

引言

本文将解释如何使用 DCOM 实现快速的客户端/服务器连接。

使用代码

本文包含两部分:

  • 服务器端实现
  • 客户端实现

让我们从服务器端实现开始

  1. 使用 Visual Studio 启动“新建 ATL COM 向导项目”。
  2. 将其命名为 TestServer。
  3. 选择服务器类型:服务。
  4. 插入新的 ATL 对象:类别-对象,对象-简单对象。
  5. 将接口命名为 IHello
  6. 添加方法 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);

现在,让我们实现客户端

  1. 启动“新建 MFC 应用程序向导,基于对话框,命名为 TestClient”。
  2. 插入资源,自定义,并将其命名为 TYPELIB。
  3. TYPELIB 资源的 ID 必须为 1。
  4. 打开 TYPELIB 资源的属性页,并将路径指定为文件 TestServer.tlb
  5. #import "..//TestServer/testserver.tlb" no_namespace 行添加到 stdafx.h
  6. includes for Afxctl.hobjbase.hinitguid.h 添加到 stdafx.h
  7. _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:LIBIDCLASSIDITERFACEID。它们都必须从 testserver.idl 中获取。我们的连接代码示例有点硬编码,但它允许在任何机器上运行客户端而无需任何注册。服务器必须在使用前注册。由于这是一个 DCOM 服务器,它可以注册为服务或本地服务器。要将服务器注册为服务,请键入:

testserver /Service

要将服务器注册为本地服务器,请键入:

testserver /RegServer

最后,让我们在远程服务器上执行 Beep() 方法。为此,只需为 Beep 按钮添加一个处理程序即可。

void CTestClientDlg::OnButtonBeep()
{
    ((CTestClientApp*)AfxGetApp())->m_pHello->Beep();
}

希望这不会很枯燥,但对您有所帮助 :-)

历史

  • 2005/02/06 - 初始文档创建。
© . All rights reserved.