我们在上一节的基础上,讨论如何实现异步的 RPC 调用。前两节演示的函数调用都是同步的,即调用函数 Hello() 时, 客户端将阻塞住直到服务端的 Hello() 函数返回。如果服务端函数需要进行一些费时的操作,例如复杂的计算、查询, 客户端只能一直阻塞在那里。这种情况下,我们可以使用异步的 RPC 提高客户端的性能。 异步的RPC是通过配置文件(.acf)来启用的: -------------------------------------------- Hello.acf: [ implicit_handle(handle_t HelloWorld_Binding) ] interface HelloWorld { [async] Hello(); // 增加了 [async] 表明这是异步调用 } 原来的接口 HelloWorld 有两个方法,Hello() 和 Shutdown(),Shutdown() 我们仍然让它是同步调用,所以在.acf文 件中不用列出。IDL 接口文件还是可以不用修改。 服务端的代码 server.c 中的 Hello() 要改成下面的样子: ------------------------------------------------------ void Hello(PRPC_ASYNC_STATE rpcAsyncHandle, const unsigned char * psz) { // 模拟一个长时间的操作 printf("Sleep 5 seconds.../n"); Sleep(5000); printf("%s/n", psz); // 表明调用已经完成 RpcAsyncCompleteCall(rpcAsyncHandle, NULL); } 服务端的其它代码不用修改。 客户端client.c中的调用方式也要换: --------------------------------- int main(int argc, char * argv[]) { // 前面都相同 ... // 下面是调用服务端的函数 RpcTryExcept { if ( _stricmp(argv[1], "SHUTDOWN") == 0 ) { Shutdown(); } else { // 初始化异步调用 RPC_ASYNC_STATE async; RpcAsyncInitializeHandle( &async, sizeof(async) ); async.UserInfo = NULL; async.NotificationType = RpcNotificationTypeNone; // 本函数能立即返回 Hello( &async, (unsigned char*)argv[1]); // 查询调用的状态 while ( RpcAsyncGetCallStatus(&async) == RPC_S_ASYNC_CALL_PENDING ) { printf("Call Hello() pending, wait 1s.../n"); Sleep(1000); } // 通知调用已经完成 RpcAsyncCompleteCall( &async, NULL ); } } RpcExcept(1) { printf( "RPC Exception %d/n", RpcExceptionCode() ); } RpcEndExcept // 后面都相同 ... } 这样客户端就实现了异步调用!
RPC 编程(三)
最新推荐文章于 2022-05-10 11:22:35 发布