首页 > 代码精文 > C/C++ > Windows RPC编程入门
2016
04-20

Windows RPC编程入门

Windows本身支持成为一个RPC服务器。MSDN里面有个很好的例子,但是,WindowsXP上面默认的RPC/tcpip功能没有打开,必须运行gpedit.msc,计算机配置->管理模版->系统->远程过程调用->用于未验证的RPC...->选择"已启动",限定项选择"无"。用VC2010express建立两个工程,按照MSDN的例子:
首先,idl文件my.idl:

[
  uuid(ba209999-0c6c-11d2-97cf-00c04f8eea45),
  version(1.0)
]
interface hw // The interface is named hw
{
   // A function that takes a zero-terminated string.
   void Hello(
      [in, string] const char* szOutput);
}

编译以后,相应的文件放到服务器端和客户端程序里面去。
服务器端实现:

#include"stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include"my_h.h"
#pragma comment(lib,"rpcrt4")
#pragma comment(lib,"ole32")
extern "C"{
void Hello(handle_t IDL_handle,const unsigned char*psz){
    printf("server:%s\n",psz);
}
void Shutdown(handle_t IDL_handle){
    RpcMgmtStopServerListening(NULL);
    RpcServerUnregisterIf(NULL,NULL,FALSE);
}
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_STATUS status;
   status = RpcServerUseProtseqEp(
      (RPC_CSTR)("ncacn_ip_tcp"), // Use TCP/IP protocol.

      RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // Backlog queue length for TCP/IP.

      (RPC_CSTR)("4747"), // TCP/IP port to use.

      NULL); // No security.

   if (status){
       printf("ServerUse failed\n");
       exit(status);}
   else printf("UseProtseqEq ok\n");
   status = RpcServerRegisterIf(
      hw_v1_0_s_ifspec, // Interface to register.

      NULL, // Use the MIDL generated entry-point vector.

      NULL);// Use the MIDL generated entry-point vector.

   if (status){
       printf("Register failed\n");
       exit(status);}
   else printf("Register if ok\n");
   // This call will not return until

   // RpcMgmtStopServerListening is called.

   status = RpcServerListen(
     1, // Recommended minimum number of threads.

     RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Recommended maximum number of threads.

     FALSE); // Start listening now.

   if (status){
       printf("Server listen failed\n");
       exit(status);}
   else printf("listen ok\n");
   return 0;
}

启动以后显示:
UseProtseqEq ok
Register if ok
客户端代码:

// myclient.cpp : Defines the entry point for the console application.

#include"stdafx.h"
#include<windows.h>
#include<stdio.h>
#include"my_h.h"
#pragma comment(lib,"rpcrt4")
#pragma comment(lib,"ole32")
int main(void){
    RPC_STATUS status;
    RPC_BINDING_HANDLE hwBinding;
    unsigned char* szStringBinding=NULL;
    status=RpcStringBindingCompose(//建立一个String Binding句柄,并不连接

        NULL,
        (RPC_CSTR)("ncacn_ip_tcp"),
        (RPC_CSTR)("localhost"),
        (RPC_CSTR)("4747"),
        NULL,
        (RPC_CSTR*)&szStringBinding);
    if(status){
        printf("StringBinding failed\n");
        exit(status);}
    printf("szString=%s\n",szStringBinding);
    status=RpcBindingFromStringBinding(
        szStringBinding,
        &hwBinding);
    if(status){
        printf("Bind from String failed:%d\n",GetLastError());
        exit(status);}
    RpcTryExcept{
                Hello(hwBinding,(RPC_CSTR)("Hello RPC World!"));
   }
   RpcExcept(1){
      printf("Runtime reported exception:%d,except=%d\n",GetLastError(),RpcExceptionCode()/*RPC_S_ACCESS_DENIED==5L*/);//这里返回了5

   }
   RpcEndExcept
   status = RpcBindingFree(&hwBinding); // Frees the binding handle.

   if (status){
       printf("Bind free failed\n");
       exit(status);}
    return 0;
}
void* __RPC_USER midl_user_allocate(size_t size){
    return malloc(size);
}
// Memory deallocation function for RPC.

void __RPC_USER midl_user_free(void* p){
    free(p);
}

运行显示:
szString=ncacn_ip_tcp:localhost[4747]

此时,服务器端显示:
server:Hello RPC World!
多次启动客户端,上面这句话显示多次。

最后编辑:
作者:小企鹅
这个作者貌似有点懒,什么都没有留下。
捐 赠如果您觉得这篇文章有用处,请支持作者!鼓励作者写出更好更多的文章!

留下一个回复