windows RPC调用过程实例详解

news2024/11/22 14:41:45

概述:windows 创建 RPC调用过程实例详解
参考文章:Remote procedure call (RPC)(远程过程调用 (RPC)) - Win32 apps | Microsoft Learn

RPC

文章目录

    • 0x01、生成 UUID 和模版(IDL)文件
    • 0x02、添加 acf 文件
    • 0x03、编译 idl 文件
    • 0x04、客户端
      • main.cpp
    • 0x05、服务端
      • main.cpp
    • 0x06、编译并运行
    • 0x07、运行示例
      • Client
      • Server

0x01、生成 UUID 和模版(IDL)文件

定义接口的第一步是使用 uuidgen 实用工具生成通用唯一标识符(UUID)。UUID使客户端和服务端能够相互识别。该工具包含在阿庄平台软件开发工具包中(SDK)。

一般安装路径位于:D:\Windows Kits\10\bin\10.0.22621.0\x64

以下命令生成 UUID 并创建名为 Hello.idl 的模版文件。

uuidgen /i /ohello.idl

模版内容大致如下:

[
    uuid(7a98c250-6808-11cf-b73b-00aa00b677a7),
    version(1.0)
]
interface hello
{
 
}

在模版中添加接口:

//file hello.idl
[
    uuid(7a98c250-6808-11cf-b73b-00aa00b677a7),
    version(1.0)
]
interface hello
{
    void HelloProc([in, string] unsigned char * pszString);
    void Shutdown(void);
}

0x02、添加 acf 文件

acf文件内容如下所示,导出接口需要与 idl 文件一致:

//file: hello.acf
[
    implicit_handle (handle_t hello_IfHandle)
] 
interface hello
{
}

0x03、编译 idl 文件

  1. 打开 visual studio,新建一个空项目

  2. 空项目中添加上述 idl文件 和 acf文件
    接口工程

  3. 编译项目

  4. 生成 hello_h.h、hello_c.c、hello_s.c

    • hello_h.h: 服务端和客户端共用文件
    • hello_c.c: 客户端文件
    • hello_s.c: 服务端文件

    需要补充说明的是,在 hello_h.h 头文件中有两个导出接口,导出接口即为rpc调用的接口。

    extern RPC_IF_HANDLE hello_v1_0_c_ifspec;
    extern RPC_IF_HANDLE hello_v1_0_s_ifspec;
    

0x04、客户端

新建工程文件如下所示:
客户端工程

main.cpp

//client.cpp
#include <iostream>
#include <string>
using namespace std;


#include "hello_h.h"

#pragma comment(lib,"Rpcrt4.lib")


void doRpcCall();

int main(int argc, char** argv)
{
    int i = 0;
    RPC_STATUS status = 0;

    unsigned char* pszNetworkAddr = NULL;
    unsigned char* pszStringBinding = NULL;

    for (i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-ip") == 0) {
            pszNetworkAddr = (unsigned char*)argv[++i];
            break;
        }
    }

    status = RpcStringBindingCompose(NULL,
        (unsigned char*)"ncacn_np",
        pszNetworkAddr,
        (unsigned char*)"\\pipe\\hello",
        NULL,
        &pszStringBinding);
    if (status != 0) {
        cout << "RpcStringBindingCompose returns: " << status << "!" << endl;
        return -1;
    }

    cout << "pszStringBinding = " << pszStringBinding << endl;
    status = RpcBindingFromStringBinding(pszStringBinding, &hello_IfHandle);
    if (status != 0) {
        cout << "RpcBindingFromStringBinding returns: " << status << "!" << endl;
        return -1;
    }

    doRpcCall();

    status = RpcStringFree(&pszStringBinding);
    if (status != 0)
        cout << "RpcStringFree returns: " << status << "!" << endl;

    status = RpcBindingFree(&hello_IfHandle);
    if (status != 0)
        cout << "RpcBindingFree returns: " << status << "!" << endl;

    cin.get();
    return 0;
}

void doRpcCall(void)
{
    char buff[1024];
    RpcTryExcept{
     while (true) {
      cout << "Please input a string param for Rpc call:" << endl;
      cin.getline(buff, 1023);
      if (strcmp(buff, "exit") == 0 || strcmp(buff, "quit") == 0) {
       Shutdown();
      }
      else {
       HelloProc((unsigned char*)buff);
       cout << "call helloproc succeed!" << endl;
      }
     }
    }

        RpcExcept(1) {
        unsigned long ulCode = RpcExceptionCode();
        cout << "RPC exception occured! code: " << ulCode << endl;
    }
    RpcEndExcept
}

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

void __RPC_USER MIDL_user_free(void* ptr)
{
    free(ptr);
}

0x05、服务端

新建工程文件如下所示:
服务端工程

main.cpp

#include <iostream>
using namespace std;

#include "hello_h.h"

#pragma comment(lib,"Rpcrt4.lib")

int main(void)
{
	RPC_STATUS status = 0;

	unsigned int mincall = 1;
	unsigned int maxcall = 20;

	status = RpcServerUseProtseqEp(
		(unsigned char*)"ncacn_np",
		maxcall,
		(unsigned char*)"\\pipe\\hello",
		NULL);
	if (status != 0) {
		cout << "RpcServerUseProtseqEp returns: " << status << endl;
		return -1;
	}

	status = RpcServerRegisterIf(
		hello_v1_0_s_ifspec,
		NULL,
		NULL);
	if (status != 0) {
		cout << "RpcServerRegisterIf returns: " << status << endl;
		return -1;
	}

	cout << "Rpc Server Begin Listening..." << endl;
	status = RpcServerListen(mincall, maxcall, FALSE);
	if (status != 0) {
		cout << "RpcServerListen returns: " << status << endl;
		return -1;
	}

	cin.get();
	return 0;
}

/************************************************************************/
/*                        MIDL malloc & free                            */
/************************************************************************/

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

void __RPC_USER MIDL_user_free(void* ptr)
{
	free(ptr);
}

/************************************************************************/
/*                       Interfaces                                     */
/************************************************************************/

void HelloProc(unsigned char* szhello)
{
	cout << szhello << endl;
}

void Shutdown(void)
{
	RPC_STATUS status = 0;

	status = RpcMgmtStopServerListening(NULL);
	if (status != 0) {
		cout << "RpcMgmtStopServerListening returns: " << status << "!" << endl;
	}

	status = RpcServerUnregisterIf(NULL, NULL, FALSE);
	if (status != 0) {
		cout << "RpcServerUnregisterIf returns: " << status << "!" << endl;
	}
}

0x06、编译并运行

分别编译客户端和服务端程序,得到 server.exe 和 client.exe

  1. 先运行 server.exe
  2. 在 client.exe 目录运行 client -ip 192.168.106.128 来启动客户端程序并与服务器端相连
  3. 在 client 的窗口输入任意字符串,回车后可看到server窗口上有显示
  4. 在 client 窗口内 输入 exit 或 quit, server 窗口关闭

0x07、运行示例

Client

Client截图

Server

Server截图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1069052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity设计模式——装饰模式

装饰模式&#xff08;Decorator&#xff09;&#xff0c;动态地给一个对象添加一些额外的职责&#xff0c;就增加功能来说&#xff0c;装饰模式比生成子类更为灵活。 Component类&#xff1a; abstract class Component : MonoBehaviour {public abstract void Operation(); …

微信小程序 movable-area 区域拖动动态组件演示

movable-area 组件在小程序中的作用是用于创建一个可移动的区域&#xff0c;可以在该区域内拖动视图或内容。这个组件常用于实现可拖动的容器或可滑动的列表等交互效果。 使用 movable-area 组件可以对其内部的 movable-view 组件进行拖动操作&#xff0c;可以通过设置不同的属…

怎么防止重要文件夹丢失?文件夹安全如何保护?

我们在使用电脑的过程中&#xff0c;会将重要数据放在文件夹中&#xff0c;那么&#xff0c;我们该怎么防止重要文件夹丢失呢&#xff1f;下面我们就一起来了解一下。 EFS加密 EFS加密可以对于NTFS卷上的文件夹进行加密&#xff0c;加密后的文件夹将只允许加密时登录系统的用户…

Bigemap 在生态环境督察工作中的应用

工具 Bigemap gis office地图软件 BIGEMAP GIS Office-全能版 Bigemap APP_卫星地图APP_高清卫星地图APP 业务背景 用户是一家科技公司&#xff0c;业务线主要是配合省生态厅环境督察应用工作&#xff0c;他们技术人员先是基于卫星遥感去发现生态环境破坏问题线索&#xff…

详解SIFT、SURF和ORB特征点检测和描述算法

文章目录 0 引言1 SIFT算法1.1 主要目的1.2 主要步骤1.3 示例代码 2 SURF算法2.1 主要目的2.2 主要步骤2.3 示例代码 3 ORB算法3.1 主要步骤3.2 代码示例 4 三者对比 0 引言 本文主要对SIFT、SURF和ORB特征点检测和描述算法进行详细的学习和比较。 ⚠️ ⚠️ ⚠️ &#xff1a…

网站为什么一定要使用SSL证书?

在现代社会&#xff0c;随着互联网的快速发展&#xff0c;越来越多的人开始使用网络来完成日常生活中的各种任务。而在这个过程中&#xff0c;网站作为网络中最重要的组成部分之一&#xff0c;也逐渐成为了人们日常生活中的不可或缺的一部分。但是&#xff0c;随着网络攻击和数…

深入分析APK文件格式

前言 最近在升级项目的 Gradle 及 AGP 版本&#xff0c;在进行APK编辑再压缩时遇到了前后压缩比不一致的问题&#xff0c;所以抽空又一总结了下 APK (ZIP) 文件格式。 无论是使用 7z 进行包体积优化&#xff0c;或是快速构建多渠道包&#xff0c;又或是V2、V3签名等都是基于 …

问卷调查中常见问题及解决方法

随着技术和市场的日益发展&#xff0c;问卷调查已经成为了人们了解客户需求和反馈的一种必要手段。但是&#xff0c;问卷调查也面临着一些问题。在本文中&#xff0c;我们将探讨一些常见问题&#xff0c;问卷调查会遇到什么问题&#xff1f;怎么解决&#xff1f;并提供一些解决…

【斗破年番】火火抱彩鳞把她整害羞啦!女王解锁新造型,身形丰满超有料

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析斗破年番系列。 斗破年番已经更新&#xff0c;这集的精彩程度可以说出乎预料。不论是节奏的把控&#xff0c;打戏的呈现还是氛围的营造都十分的出彩。尤其是在萧炎施展三千雷动时运用的三年之约时的BGM简直让观感体验瞬间…

审计和风控做什么——企业审计和风控工作的相同和不同

审计和风控是现代企业管理中两个重要的领域。它们在企业和社会组织的运营中发挥着重要作用。本文将探讨审计和风控的异同点。 一、审计和风控的定义 审计是指对一个组织或个人财务报表、业务过程、内部控制和风险管理等方面进行审核的活动。它的目的是发现潜在的问题、风险和控…

CUDA学习笔记2——CUDA程序基本框架

CUDA向量运算 CUDA程序的基本框架为&#xff1a; 头文件包含 常量定义/宏定义 C 自定义函数和CUDA核函数声明 int main(void) { 分配主机与设备内存 初始化主机中的数据 将部分数据从主机拷贝至设备 调用核函数在设备中进行计算 将部分数据从设备拷贝至主机 释放主机与设备内存…

采集网页数据保存到文本文件---爬取古诗文网站

访问古诗文网站&#xff08;https://so.gushiwen.org/mingju/&#xff09; 会显示出这个页面&#xff0c;里面包含了很多的名句&#xff0c;点击某一个名句&#xff08;比如点击无处不伤心&#xff0c;轻尘在玉琴&#xff09;就会出现完整的古诗 我们点击鼠标右键&#xff0c;点…

【C++设计模式之责任链模式:行为型】分析及示例

简介 责任链模式是一种行为型设计模式&#xff0c;它允许将请求沿着处理链传递&#xff0c;直到有一个处理器能够处理该请求。这种模式将请求的发送者和接收者解耦&#xff0c;同时提供了更高的灵活性和可扩展性。 描述 责任链模式由多个处理器组成一个处理链&#xff0c;每…

如何批量获取拼多多商品详情数据,拼多多商品详情API接口

批量获取拼多多商品详情数据可以采用以下方式&#xff1a; 使用拼多多开放平台API接口。 拼多多开放平台提供了API接口&#xff0c;可以通过API接口获取拼多多平台上的商品信息&#xff0c;使用API接口需要进行权限申请和认证&#xff0c;操作较为复杂。使用第三方工具。 市面…

Transformer预测 | Pytorch实现基于Transformer的锂电池寿命预测(NASA数据集)

文章目录 效果一览文章概述模型描述程序设计参考资料效果一览 文章概述 Pytorch实现基于Transformer 的锂电池寿命预测,环境为pytorch 1.8.0,pandas 0.24.2 随着充放电次数的增加,锂电池的性能逐渐下降。电池的性能可以用容量来表示,故寿命预测 (RUL) 可以定义如下: SOH(t…

网络安全(黑客)——自学篇

什么是网络安全&#xff1f; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻…

基于FPGA的I2C读写EEPROM

文章目录 前言一、I2C协议1.1 I2C协议简介1.2 物理层1.3 协议层 二、EEPROM2.1 型号及硬件规格2.2 各种读写时序 三、状态机设计四、项目源码&#xff1a;五、实现效果参考资料 前言 本次项目所用开发板FPGA芯片型号为&#xff1a;EP4CE6F17C8 EEPROM芯片型号为&#xff1a;24L…

[C++从入门到精通] 11.回顾类内初始化、默认构造函数、=default

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…

Python爬虫(二十二)_selenium案例:模拟登陆豆瓣

本篇博客主要用于介绍如何使用seleniumphantomJS模拟登陆豆瓣&#xff0c;没有考虑验证码的问题&#xff0c;更多内容&#xff0c;请参考&#xff1a;Python学习指南 #-*- coding:utf-8 -*-from selenium import webdriver from selenium.webdriver.common.keys import Keysimp…

辅助寄存器是干什么用的

目录 请问CPU 的 MREQ 引脚和 IORQ 引脚分别是干什么用的 那这里的引脚是什么含义呢&#xff1f; 程序是指令和数据的集合 辅助寄存器是干什么用的 寄存器的用途取决于它的类型 PC 寄存器也叫作“程序指针”&#xff0c;存储着指向 CPU 接下来 要执行的指令的地址。PC 寄存…