随笔 - 514, 文章 - 0, 评论 - 921, 引用 - 0
数据加载中……

由浅入深,举例讲解RPC(一)

 

关于RPC的文章很多,但是系统讲解的很少。下面我将写一个系列报道。用代码和论述来把rpc来讲讲清楚。

这篇就是开始第一篇了。

 

由于工作比较忙。我们抽出一个星期的时间,有时间会写一点。把这个系列写完。所以,有可能每个系列都比较短些。

从最基本的讲起,让大家彻底明白RPC.

 

好了废话不多说了。正是开始。

 

 

首先,你要用RPC,必须先搞清楚什么是IDL.

 

Rpc是什么?

http://www.cppblog.com/alantop/archive/2007/07/09/27717.html

IDL是什么?

http://www.cppblog.com/alantop/archive/2007/07/09/27725.html

 

下来,举个例子。怎么样把一个标准程序改成用IDL语言写的程序。

 

这是一个标准程序。

// File Standalone.cpp

#include <iostream>

 

// Future server function.

void Output(const char* szOutput)

{

   std::cout << szOutput << std::endl;

}

 

int main()

{

   // Future client call.

   Output("Hello Lonely World!");

}

 

下来看我们怎么把它改为一个标准IDL语言的程序

IDL语言定义接口:

// File Example1.idl

[

   // A unique identifier that distinguishes this

   // interface from other interfaces.

   uuid(00000001-EAF3-4A7A-A0F2-BCE4C30DA77E),

 

   // This is version 1.0 of this interface.

   version(1.0),

 

   // This interface will use an implicit binding

   // handle named hExample1Binding.

   implicit_handle(handle_t hExample1Binding)

]

interface Example1 // The interface is named Example1

{

   // A function that takes a zero-terminated string.

   void Output(

      [in, string] const char* szOutput);

}

上面这个文件是我们用idl语言定义的,我们定义了一个接口Example1, 它带有uuidversion. 这个接口里定义了一个函数Output.

 

UUID是什么?

http://www.cppblog.com/alantop/archive/2007/07/09/27726.html

 

 

接口的implicit_handle属性,我们后面再讨论。

 

接下来干什么呢?

我们为了在程序中使用idl,必须通过通过编译器(midl.exe)把它翻译成客户代理和服务器存根, 代理和存根将在后面被我们的编译器(windows平台下的cl.exe)所使用。

 

 

改好的服务器端程序:

// File Example1Server.cpp

#include <iostream>

#include "Example1.h"

 

// Server function.

void Output(const char* szOutput)

{

   std::cout << szOutput << std::endl;

}

 

int main()

{

   RPC_STATUS status;

 

   // Uses the protocol combined with the endpoint for receiving

   // remote procedure calls.

   status = RpcServerUseProtseqEp(

      reinterpret_cast<unsigned char*>("ncacn_ip_tcp"), // Use TCP/IP

                                                        // protocol.

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

      reinterpret_cast<unsigned char*>("4747"), // TCP/IP port to use.

      NULL); // No security.

 

   if (status)

      exit(status);

 

   // Registers the Example1 interface.

   status = RpcServerRegisterIf(

      Example1_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)

      exit(status);

 

   // Start to listen for remote procedure

   // calls for all registered interfaces.

   // 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)

      exit(status);

}

 

// Memory allocation function for RPC.

// The runtime uses these two functions for allocating/deallocating

// enough memory to pass the string to the server.

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);

}

 

这是初始化,和注册接口的代码。

 

现在看看怎么写客户端

// File Example1Client.cpp

#include <iostream>

#include "Example1.h"

 

int main()

{

   RPC_STATUS status;

   unsigned char* szStringBinding = NULL;

 

   // Creates a string binding handle.

   // This function is nothing more than a printf.

   // Connection is not done here.

   status = RpcStringBindingCompose(

      NULL, // UUID to bind to.

      reinterpret_cast<unsigned char*>("ncacn_ip_tcp"), // Use TCP/IP

                                                        // protocol.

      reinterpret_cast<unsigned char*>("localhost"), // TCP/IP network

                                                     // address to use.

      reinterpret_cast<unsigned char*>("4747"), // TCP/IP port to use.

      NULL, // Protocol dependent network options to use.

      &szStringBinding); // String binding output.

 

   if (status)

      exit(status);

 

   // Validates the format of the string binding handle and converts

   // it to a binding handle.

   // Connection is not done here either.

   status = RpcBindingFromStringBinding(

      szStringBinding, // The string binding to validate.

      &hExample1Binding); // Put the result in the implicit binding

                          // handle defined in the IDL file.

 

   if (status)

      exit(status);

 

   RpcTryExcept

   {

      // Calls the RPC function. The hExample1Binding binding handle

      // is used implicitly.

      // Connection is done here.

      Output("Hello RPC World!");

   }

   RpcExcept(1)

   {

      std::cerr << "Runtime reported exception " << RpcExceptionCode()

                << std::endl;

   }

   RpcEndExcept

 

   // Free the memory allocated by a string.

   status = RpcStringFree(

      &szStringBinding); // String to be freed.

 

   if (status)

      exit(status);

 

   // Releases binding handle resources and disconnects from the server.

   status = RpcBindingFree(

      &hExample1Binding); // Frees the implicit binding handle defined in

                          // the IDL file.

 

   if (status)

      exit(status);

}

 

// Memory allocation function for RPC.

// The runtime uses these two functions for allocating/deallocating

// enough memory to pass the string to the server.

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);

}

 

posted on 2007-07-09 12:41 AlanTop 阅读(4034) 评论(3)  编辑 收藏 引用 所属分类: COMC++

评论

# re: 由浅入深,举例讲解RPC(一)[未登录]  回复  更多评论   

好文章!
2007-07-09 17:13 | 111

# re: 由浅入深,举例讲解RPC(一)  回复  更多评论   

好,顶!!
2007-07-13 17:07 | 黄大仙

# re: 由浅入深,举例讲解RPC(一)  回复  更多评论   

后面还有吗?谢谢
2009-04-05 23:54 | 萤火虫

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理