时间流逝,一转眼已经毕业5年了,感觉也错过了不少时光,也未能给生活流下点点滴滴。我是一个打杂程序员,工作几年,接触的东西多而杂,感觉自己已经没有一个方向,现在开始坚持写些东西,以回顾所学的东西,也给新的东西留下一点记录。接下来先从windows端的一些开发记录下。 昨天突然想了解一下win32的RPC实现,所以在网上找了找资料,就搞了起来,利用rpc,可以使不同进程之前调用。先是服务端,新建vs2015工程,然后新建IDL(Interface description language)文件,如下 RPCDvrServer.idl
import "oaidl.idl";
import "ocidl.idl";
[
uuid(50272674-4DEB-42D4-A37D-BE311DD06E2A), // 唯一的UUID,用 GUIDGen 生成
version(1.0)
]
interface RPCDvrServer
{
error_status_t GetServerName([out, size_is(len)]char *pszName,[in]long len);
error_status_t Add([in] long num1, [in] long num2, [out] long*res);
error_status_t ShutDown();
}
然后再新建一个acf文件RPCDvrServer.acf
[
implicit_handle (handle_t RPCDvrServer_IfHandle)
]
interface RPCDvrServer
{
}
定义好接口后,现在来开始编写服务端,RpcServer.cpp
// RpcServer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "IDvrServer_h.h"
#define _CRT_SECURE_NO_WARNINGS 1
#pragma comment( lib, "Rpcrt4.lib" )
void StopDvrService();
long StartDvrService();
error_status_t GetServerName(
/* [size_is][out] */ unsigned char *pszName,
/* [in] */ long len)
{
strncpy((char*)pszName, "RPCDvrServer", len);
pszName[len - 1] = '\0';
printf("服务已经启动!\n");
return 0;
}
error_status_t Add(
/* [in] */ long num1,
/* [in] */ long num2,
/* [out] */ long *rtn)
{
*rtn = num1 + num2;
printf("sum is:%ld\n", *rtn);
return 0;
}
error_status_t ShutDown(void)
{
StopDvrService();
printf("服务已经关闭!\n");
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);
}
long StartDvrService()
{
//RPC技术发送Local请求时使用ncalrpc协议,发送Remote请求时使用ncacn_ip_tcp或者ncacn_np协议,前者微软更推荐
RPC_STATUS rpcStats = RpcServerUseProtseqEpW(reinterpret_cast<RPC_WSTR>(L"ncalrpc"),
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
reinterpret_cast<RPC_WSTR>(L"msmpq_dvr"),
NULL);
if (rpcStats)
exit(rpcStats);
rpcStats = RpcServerRegisterIf(RPCDvrServer_v1_0_s_ifspec, NULL, NULL);
if (rpcStats)
exit(rpcStats);
unsigned int fDontWait = false;
rpcStats = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, fDontWait);
if (rpcStats)
exit(rpcStats);
return 0;
}
void StopDvrService()
{
RPC_STATUS rpcStatus;
rpcStatus = RpcMgmtStopServerListening(NULL);
rpcStatus = RpcServerUnregisterIf(NULL, NULL, FALSE);
}
int main()
{
StartDvrService();
return 0;
}
然后新建vs2015工程客户端
引入IDvrServer_h.h和IDvrServer_c.c,新建测试代码RpcClient.cpp
// RcpClient.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <rpc.h>
#include <tchar.h>
#include <stdio.h>
#include"IDvrServer_h.h"
#pragma comment( lib, "Rpcrt4.lib" )
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);
}
int main()
{
RPC_WSTR pszStringBinding = NULL;
RPC_STATUS rpcStatus = RpcStringBindingComposeW(NULL,
reinterpret_cast<RPC_WSTR>(L"ncalrpc"),
NULL,
reinterpret_cast<RPC_WSTR>(L"msmpq_dvr"),
NULL,
&pszStringBinding);
if (rpcStatus)
exit(rpcStatus);
rpcStatus = RpcBindingFromStringBinding(pszStringBinding,
&RPCDvrServer_IfHandle);
if (rpcStatus)
exit(rpcStatus);
unsigned char name[100];
RpcTryExcept
{
GetServerName(name, 100);
}
RpcExcept(1)
{
unsigned long ulCode = RpcExceptionCode();
printf("抛出异常0x%lx = %ld。\n", ulCode, ulCode);
}
RpcEndExcept
long i = 0;
long sum = 0;
while (true) {
Sleep(1000);
i++;
RpcTryExcept
{
Add(i,i + 1,&sum);
printf("sum is:%ld\n", sum);
}
RpcExcept(1)
{
unsigned long ulCode = RpcExceptionCode();
printf("抛出异常0x%lx = %ld。\n", ulCode, ulCode);
}
RpcEndExcept
}
return 0;
}
致此可以跑通调用 ,后续 会研究如何回调、异步,等 等 ,也许也不会再研究,看心情,哈哈