Windows RPC远程过程调用(入门)

1 篇文章 0 订阅
1 篇文章 0 订阅

前言:

    编写一个win32 RPC demo

具体内容:

    1:编写IDL(Interface Description Language,接口描述语言):

     test.idl:

[
	uuid("F211474B-E9DF-4682-B779-DFAA64B56F9F"),
	version(1.0)
]

interface HelloWorld
{
	int intAdd(int x, int y);
}

注:uuid可以使用vs自动create guid工具生成,具体在 tools->create GUID

    在编写一个应用程序配置文件(.acf),它的作用是对RPC接口进行配置:

    test.acf:

[
	implicit_handle(handle_t test_Binding)
]

interface HelloWorld
{
}

    编译idl文件:

    在cmd或者vs终端运行命令:

         midl test.idl

    生成test.h, test_c.c, test_s.c文件,其中test.h为公用头文件,test_c.c为客户端文件,test_s.c为服务端文件


    2:编写代码

    在visual studio中新建win32 console application工程

Server端:

    首先,引入刚才midl生成的test.h 和 test_s.c文件,新建一个调用.cpp文件,文件结构如下图:

    

    其次,引入rpcrt4.lib依赖包,操作过程为:

    右键工程属性,在Linker->Input->Additional Dependencies中添加rpcrt4.lib

     

    等这些准备工作做好后,就可以开始书写代码了,具体代码内容如下:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

#include "../../../test.h"

int intAdd(int x, int y) 
{
	printf("%d + %d = %d\n", x, y, x + y);
	return x + y;
}


int wmain(int argc, wchar_t* argv[]) 
{	
	// 采用tcp协议,13521端口
	RpcServerUseProtseqEp((RPC_WSTR)L"ncacn_ip_tcp", RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
		(RPC_WSTR)L"13521", NULL);
	// 注册,HelloWorld_v1_0_s_ifspec定义域头文件test.h
	// 注意:从Windows XP SP2开始,增强了安全性的要求,如果用RpcServerRegisterIf()注册接口,客户端调用时会出现
	// RpcExceptionCode() == 5,即Access Denied的错误,因此,必须用RpcServerRegisterIfEx带RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH标志
	// 允许客户端直接调用
	RpcServerRegisterIfEx(HelloWorld_v1_0_s_ifspec, NULL, NULL, RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH, 0, NULL);
	// 开始监听,本函数将一直阻塞
	RPC_STATUS result = RpcServerListen(1, 20, FALSE);

	printf("end-------------RPC_STATUS: %d\n", result);

	return 0;
}


// 下面的函数是为了满足链接需要而写的,没有的话会出现链接错误
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);
}

注:

a:这里采用tcp的形式进行通信,也可以采用命名管道的方式

b、RpcServerRegisterIfEx调用,具体看注释说明


以上就是服务端的代码


客户端:

    前两部操作同服务端,区别是客户端引入的是test_c.c文件

    客户端代码如下:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>

#include "../../../test.h"

int wmain(int argc, wchar_t* argv[])
{
	if (argc < 2) {
		_wsetlocale(LC_ALL, L"chs");
		wprintf_s(L"请输入ip地址,格式为 testClient.exe xxx.xxx.xxx.xxx\n");
		Sleep(2000);
		return 0;
	}

	wprintf_s(L"server ip: %s\n", argv[1]);

	RPC_WSTR pszStringBinding = NULL;
	int x, y, rval;

	RpcStringBindingCompose(
		NULL,
		(RPC_WSTR)L"ncacn_ip_tcp",
		(RPC_WSTR)argv[1] /*NULL*/,
		(RPC_WSTR)L"13521",
		NULL,
		&pszStringBinding
	);

	// 绑定接口,这里要和 test.acf 的配置一致,那么就是test_Binding
	RpcBindingFromStringBinding(pszStringBinding, &test_Binding);

	// 下面是调用服务端的函数了
	RpcTryExcept
	{
		while (1)
		{
			printf("Input two integer: ");
			scanf_s("%d %d", &x, &y);
			rval = intAdd(x, y);
			printf("%d\n", rval);

			Sleep(2000);
		}

	}
		RpcExcept(1)
	{
		printf("RPC Exception %d\n", RpcExceptionCode());
		Sleep(2000);
	}
	RpcEndExcept


		// 释放资源
		RpcStringFree(&pszStringBinding);
	RpcBindingFree(&test_Binding);

	return 0;
}

// 下面的函数是为了满足链接需要而写的,没有的话会出现链接错误
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);
}

运行后结果如下:


由于是本机运行,所以直接输入了localhost,如果换成其他机器  可以输入对应ip地址


demo地址:

https://download.csdn.net/download/herojuice/10537284


说明:

以上内容大部分来自网上,这里稍做了一些整理,这里仅做记录总结

        




    
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值