回覆列表
  • 1 # 使用者5527968807830

    第1步:編寫 IDL(Interface Description Language,介面描述語言)檔案-------------------------------------------------------------------------IDL 是一個通用的工業標準語言,大家應該不陌生,因為 COM 裡面也是用它來描述介面的。Hello.idl:[ uuid("4556509F-618A-46CF-AB3D-ED736ED66477"), // 唯一的UUID,用 GUIDGen 生成 version(1.0)]interface HelloWorld { // 我們定義的方法 void Hello([in,string]const char * psz); void Shutdown(void); }一個可選的檔案是應用程式配置檔案(.acf),它的作用是對 RPC 介面進行配置,例如下面的 Hello.acf 檔案:Hello.acf:[ implicit_handle(handle_t HelloWorld_Binding) ] interface HelloWorld{}上面定義了 implicit_handle,這樣客戶端將繫結控制代碼 HelloWorld_Binding 了,後面的客戶端程式碼中我們會看到。編譯 IDL 檔案:>midl Hello.idlMicrosoft (R) 32b/64b MIDL Compiler Version 6.00.0366Copyright (c) Microsoft Corporation 1991-2002. All rights reserved.Processing .\Hello.idlHello.idlProcessing .\Hello.acfHello.acf我們可以看到自動生成了 Hello.h, Hello_s.c, Hello_c.c 檔案,這些叫做 rpc stub 程式,不過我們可以不管這個概念,我們只需要知道 Hello.h 裡面定義了一個extern RPC_IF_HANDLE HelloWorld_v1_0_s_ifspec;這個 RPC_IF_HANDLE 將在後面用到。第2步:編寫服務端程式------------------------------------------------------------------------- 第1步中我們已經約定了呼叫的介面,那麼現在我們開始實現其服務端。程式碼如下:server.c#include <stdlib.h>#include <stdio.h>#include "Hello.h" // 引用MIDL 生成的標頭檔案/** * 這是我們在IDL 中定義的介面方法 * 需要注意一點,IDL 裡面的宣告是:void Hello([in,string]const char * psz); * 但是這裡變成了const unsigned char *,為什麼呢? * 參見MSDN 中的MIDL Command-Line Reference -> /char Switch * 預設的編譯選項,對 IDL 中的char 按照unsigned char 處理 */void Hello(const unsigned char * psz){ printf("%s\n", psz);}/** 這也是我們在IDL 中定義的介面方法,提供關閉server 的機制*/void Shutdown(void){ // 下面的操作將導致 RpcServerListen() 退出 RpcMgmtStopServerListening(NULL); RpcServerUnregisterIf(NULL, NULL, FALSE);}int main(int argc,char * argv[]){ // 用Named Pipe 作為RPC 的通道,這樣EndPoint 引數就是Named Pipe 的名字 // 按照Named Pipe 的命名規範,\pipe\pipename,其中pipename 可以是除了\ // 之外的任意字元,那麼這裡用一個GUID 串來命名,可以保證不會重複 RpcServerUseProtseqEp((unsigned char *)"ncacn_np", 20, (unsigned char *)"\\pipe\\{8dd50205-3108-498f-96e8-dbc4ec074cf9}", NULL); // 註冊介面,HelloWorld_v1_0_s_ifspec 是在MIDL 生成的Hello.h 中定義的 RpcServerRegisterIf(HelloWorld_v1_0_s_ifspec, NULL, NULL); // 開始監聽,本函式將一直阻塞 RpcServerListen(1,20,FALSE); 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);}編譯:>cl /D_WIN32_WINNT=0x500 server.c Hello_s.c rpcrt4.lib用於 80x86 的 Microsoft (R) 32 位 C/C++ 最佳化編譯器 14.00.50727.42 版版權所有(C) Microsoft Corporation。保留所有權利。server.cHello_s.c正在生成程式碼...Microsoft (R) Incremental Linker Version 8.00.50727.42Copyright (C) Microsoft Corporation. All rights reserved./out:server.exeserver.objHello_s.objrpcrt4.lib編譯時為什麼要指定 _WIN32_WINNT=0x500 呢?因為如果沒有的話會報告下面的錯誤:Hello_s.c(88) : fatal error C1189: #error : You need a Windows 2000 or later torun this stub because it uses these features:第3步:編寫客戶端程式------------------------------------------------------------------------- 客戶端的程式碼:client.c#include <stdlib.h>#include <stdio.h>#include <string.h>#include "Hello.h" // 引用MIDL 生成的標頭檔案int main(int argc, char * argv[]){ unsigned char * pszStringBinding = NULL; if ( argc != 2 ) { printf("Usage:%s <Hello Text>\n", argv[0]); return 1; } // 用Named Pipe 作為RPC 的通道。參見server.c 中的RpcServerUseProtseqEp() 部分 // 第3 個引數NetworkAddr 如果取NULL,那麼就是連線本機服務 // 否則要取\\\\servername 這樣的格式,例如你的計算機名為jack,那麼就是\\jack RpcStringBindingCompose( NULL, (unsigned char*)"ncacn_np", /*(unsigned char*)"\\\\servername"*/ NULL, (unsigned char*)"\\pipe\\{8dd50205-3108-498f-96e8-dbc4ec074cf9}", NULL, &pszStringBinding ); // 繫結介面,這裡要和 Hello.acf 的配置一致,那麼就是HelloWorld_Binding RpcBindingFromStringBinding(pszStringBinding, & HelloWorld_Binding ); // 下面是呼叫服務端的函數了 RpcTryExcept { if ( _stricmp(argv[1], "SHUTDOWN") == 0 ) { Shutdown(); } else { Hello((unsigned char*)argv[1]); } } RpcExcept(1) { printf( "RPC Exception %d\n", RpcExceptionCode() ); } RpcEndExcept// 釋放資源 RpcStringFree(&pszStringBinding); RpcBindingFree(&HelloWorld_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);}編譯:>cl /D_WIN32_WINNT=0x500 client.c Hello_c.c rpcrt4.lib用於 80x86 的 Microsoft (R) 32 位 C/C++ 最佳化編譯器 14.00.50727.42 版版權所有(C) Microsoft Corporation。保留所有權利。client.cHello_c.c正在生成程式碼...Microsoft (R) Incremental Linker Version 8.00.50727.42Copyright (C) Microsoft Corporation. All rights reserved./out:client.execlient.objHello_c.objrpcrt4.lib第4步:測試:------------------------------------------------------------------------- 執行 server.exe,將彈出一個 console 視窗,等待客戶端呼叫。執行客戶端 client.exe:>client hello可以看到 server.exe 的 console 窗口出現 hello 的字串。>client shutdownserver.exe 退出。

  • 中秋節和大豐收的關聯?
  • 現在比較火的幾部電視劇,《招搖》,《逆流而上的你》等等,你最喜歡哪部?為什麼?