C++第五十七篇——RPC进程间通信

第一步:新建一个空项目

 第二步:新建一个IDL

 第三步:生成一个GUID,编写RPCConn.idl

 RPCConn.idl

import "oaidl.idl";
import "ocidl.idl";

[
    uuid(1BA624D4-DC7D-484C-AF8C-0EF86C4A0555),
    version(1.0)
]
interface RPCConn
{
    int Add(
        [in] int a,
        [in] int b
    );
    unsigned long long GetLastInputInfoTime();
}
View Code

 

第四步:右击RPCConn.idl进行编译

 

 将RPCConn_s.c和RPCConn_h.h拷贝到RPC的服务端,将RPCConn_c.c和RPCConn_h.h拷贝到RPC的客户端。

第五步:新建一个服务端空项目RPCServer,将RPCConn_s.c和RPCConn_h.h拷贝过去,并添加现有项。

 第六步:新建一个RPCServer.cpp

#include "RPCConn_h.h"
#include <Windows.h>
#include <iostream>
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")


int main()
{
    RPC_STATUS status = RPC_S_OK;
    // 注册接口
    status = RpcServerRegisterIf(
        RPCConn_v1_0_s_ifspec,            // 要注册的接口
        NULL,                            // 指向与EPV参数关联的UUID
        NULL                            // 管理器例程的入口点向量EPV
    );

    if (status != RPC_S_OK)
    {
        printf("注册接口失败。错误代码:0x%08X\n", status);
        return status;
    }
    printf("注册接口完成\n");
    // 使服务器在本地可用
    status = RpcServerUseProtseq(
        (RPC_WSTR)L"ncalrpc",
        RPC_C_PROTSEQ_MAX_REQS_DEFAULT,    // Protseq dependent parameter
        NULL                                // Always specify NULL here.
    );

    if (status != RPC_S_OK)
    {
        printf("指定使用协议失败。错误代码:0x%08X\n", status);
        return status;
    }
    printf("指定ncalrpc协议完成\n");
    // 获取绑定向量
    RPC_BINDING_VECTOR* rpcBindingVector;
    status = RpcServerInqBindings(&rpcBindingVector);
    if (status != RPC_S_OK)
    {
        printf("获取绑定向量失败。错误代码:0x%08X\n", status);
        return status;
    }
    printf("绑定向量完成\n");
    // 注册终结点
    status = RpcEpRegister(
        RPCConn_v1_0_s_ifspec,                // 注册终结点的接口
        rpcBindingVector,                    // 指定绑定句柄的向量
        NULL,                                // 指向服务器提供的对象UUID的向量指针
        NULL                                // 字符串注释指针
    );
    if (status != RPC_S_OK)
    {
        printf("注册终结点失败。错误代码:0x%08X\n", status);
        return status;
    }
    printf("注册终结点完成\n");
    printf("开始侦听客户端......\n");
    // 侦听客户端调用
    status = RpcServerListen(
        1,                                    // 服务器中创建和维护的最小线程数
        RPC_C_LISTEN_MAX_CALLS_DEFAULT,        // 建议的最大并发远程过程调用数
        0                                    //    控制监听返回的标志 0:在完成所有回调前不返回 !0:完成函数处理后立即返回
    );
    if (status != RPC_S_OK)
    {
        printf("侦听客户端调用失败。错误代码:0x%08X\n", status);
        return status;
    }
    return status;
}


int Add(
    /* [in] */ handle_t IDL_handle,
    /* [in] */ int a,
    /* [in] */ int b)
{
    printf("Calling Add:%d + %d = %d\n", a, b, a + b);
    return a + b;
}

unsigned long long GetLastInputInfoTime(
    /* [in] */ handle_t IDL_handle)
{
    LASTINPUTINFO lastInputInfo;
    lastInputInfo.cbSize = sizeof(lastInputInfo);
    GetLastInputInfo(&lastInputInfo);
    ULONGLONG time = GetTickCount64() - lastInputInfo.dwTime;
    printf("Time:%llu\n", time);
    return time;
}

/******************************************************/
/*         MIDL allocate and free                     */
/******************************************************/

void __RPC_FAR* __RPC_USER midl_user_allocate(size_t len)
{
    return(malloc(len));
}

void __RPC_USER midl_user_free(void __RPC_FAR* ptr)
{
    free(ptr);
}
View Code

 

第七步:为RPCServer的链接器添加一个rpcrt4.lib文件

 第八步:将RPCServer设置为启动项目并运行起来,可以在任务管理器的进程中看到。

第九步:创建一个RPC客户端空项目,将RPCConn_c.c和RPCConn_h.h拷贝进去

 第十步:新建一个RPCClient.cpp

#include "RPCConn_h.h"
#include <Windows.h>
#include <iostream>

int main()
{
    RPC_STATUS status = RPC_S_OK;
    unsigned short* StringBinding;
    RPC_BINDING_HANDLE BindingHandle;
    status = RpcStringBindingCompose(
        NULL,                           // Object UUID
        (RPC_WSTR)L"ncalrpc",           // Protocol sequence to use
        NULL,                           // Server DNS or Netbios Name
        NULL,
        NULL,
        &StringBinding
    );
    if (status != RPC_S_OK)
    {
        printf("获取绑定字符串失败。错误代码:0x%08X\n", status);
        return status;
    }
    status = RpcBindingFromStringBinding(StringBinding, &BindingHandle);
    if (status != RPC_S_OK)
    {
        printf("获取绑定句柄失败。错误代码:0x%08X\n", status);
        return status;
    }
    RpcStringFree(&StringBinding);
    printf("请输入两个数字:\n");
    int a = 0, b = 0;
    scanf_s("%d%d", &a, &b);
    printf("%d + %d = %d\n", a, b, Add(BindingHandle, a, b));
    system("pause");
    return status;
}

/******************************************************/
/*         MIDL allocate and free                     */
/******************************************************/

void __RPC_FAR* __RPC_USER midl_user_allocate(size_t len)
{
    return(malloc(len));
}

void __RPC_USER midl_user_free(void __RPC_FAR* ptr)
{
    free(ptr);
}
View Code

第十一步:为RPCClient的链接器添加一个rpcrt4.lib文件。

第十二步:将RPCClient设为一个启动项目并运行

 成功通信。

 

posted @ 2024-03-28 16:13  o云淡风轻o  阅读(62)  评论(0编辑  收藏  举报