RPC進程通信小模型

這幾天因爲工作的需要,學習了一下RPC進程通信,RPC確實是個好東西啊,可以遠程,可以本機,可以跨系統,而且處理過程,以及消息傳遞非常隱祕,安全性極高,函數的實現過程全部是在服務器端,而所有的客戶端本身也可以作爲一個服務器,也就是所有的程序初始化的時候都建立一個RPC的服務,這樣所有的進程就想訪問誰就訪問誰了。

首先,第一步,是要通過IDL生成接口,提供給程序使用,代碼很簡單,我就添加三個簡單的函數:

import "oaidl.idl";
import "ocidl.idl";


[  
  uuid(EA5B1108-7593-423e-8C05-313BF6E62CC2),  
  version(1.0)  
]  
interface hw
{  
   void Hello(  [in, string] const char * szOutput ); 
   void SendMessageEx( [in,string] const char * szMsg );
   int Add([in] const int Add1,[in] const int Add2);
}  
然後編譯成功後生成三個文件rpc_h.h , rpc_c.c , rpc_s.c,這三個函數分別的用途是第一個:聲明函數和一些其他的信息,後面兩個分別是client和server端的定義的一些代碼,我們單純的使用就好。

接下來,我們來寫server端的代碼:

<pre name="code" class="cpp">#include"stdafx.h"  
#include<stdio.h>  
#include<stdlib.h>  
#include "../rpc_five/rpc_h.h"  //重點的兩個文件要包含進去另外還有兩個靜態庫
#include "../rpc_five/rpc_s.c"
#pragma comment(lib,"rpcrt4")  
#pragma comment(lib,"ole32")  

void Hello(handle_t IDL_handle,const unsigned char*psz){  
	printf("server:%s\n",psz);  
}  

//////////////SendMessageEx/////////////////////////////////
void SendMessageEx(handle_t IDL_handle, const unsigned char *szMsg)
{
	char  Temp[16];
	sprintf( Temp ,"%s" , szMsg );
	if ( 0 == strcmp(Temp,"quit"))
	{
		RpcMgmtStopServerListening(NULL);  
		RpcServerUnregisterIf(NULL,NULL,FALSE);  
	}
	printf("sendmessage->%s\n",Temp);
}
////////////////////////////////////////////////////////////

int Add(handle_t IDL_handle, const int Add1, const int Add2)
{
	printf("Sum = %d",Add1 + Add2);
	return Add1 + Add2;
}
void Shutdown(handle_t IDL_handle){  
	RpcMgmtStopServerListening(NULL);  
	RpcServerUnregisterIf(NULL,NULL,FALSE);  
}  
void*  __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"), //表面使用TCP/IP協議,另外還有三個,管道,RPC,UDP協議  

		RPC_C_PROTSEQ_MAX_REQS_DEFAULT, //max長度

		(RPC_CSTR)("888"), //端口號

		NULL); //安全屬性

	if (status)
<span style="white-space:pre">	</span>{  
	<span style="white-space:pre">	</span>printf("ServerUse failed\n");  
	<span style="white-space:pre">	</span>exit(status);
<span style="white-space:pre">	</span>}  
	else 
<span style="white-space:pre">	</span>{
<span style="white-space:pre">	</span>printf("UseProtseqEq ok\n");  
<span style="white-space:pre">	</span>}

//<span style="white-space:pre">	</span>RpcServerRegisterIf(hw_v1_0_s_ifspec, NULL, NULL);  普通版本的註冊,個人覺得不好用,建議使用加強版
	RpcServerRegisterIfEx(  
		hw_v1_0_s_ifspec, // 接口名稱
		NULL,  
		NULL,
		RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH,  
		RPC_C_LISTEN_MAX_CALLS_DEFAULT,  
		NULL);  

	if (status)
<span style="white-space:pre">	</span>{  
		printf("Register failed\n");  
		exit(status);
<span style="white-space:pre">	</span>}  
	else 
<span style="white-space:pre">	</span>{
<span style="white-space:pre">	</span>printf("Register if ok\n");  
<span style="white-space:pre">	</span>}

	status = RpcServerListen( 1,RPC_C_LISTEN_MAX_CALLS_DEFAULT,FALSE ); //建立之後處於阻塞監聽狀態

	if (status)
<span style="white-space:pre">	</span>{  
		printf("Server listen failed\n");  
		exit(status);
<span style="white-space:pre">	</span>}  
	else 
<span style="white-space:pre">	</span>{
<span style="white-space:pre">	</span>printf("listen ok\n");  
	}
<span style="white-space:pre">	</span>return 0;  
}

客戶端程序其實跟服務器端程序寫法差不多:

#include "stdafx.h"  
#include "windows.h" 
#include "stdio.h"  

#include "../rpc_five/rpc_h.h"
#include "../rpc_five/rpc_c.c"
#pragma comment(lib,"rpcrt4")  
#pragma comment(lib,"ole32")  

<span style="white-space:pre">	</span>int main()
<span style="white-space:pre">	</span>{  
	RPC_STATUS status;  
	RPC_BINDING_HANDLE hwBinding;  
	unsigned char* szStringBinding=NULL;  
	status=RpcStringBindingCompose(//建立一個String Binding句柄,並不連接  
		NULL,  
		(RPC_CSTR)("ncacn_ip_tcp"),
		(RPC_CSTR)("127.0.0.1"),
		(RPC_CSTR)("888"),
		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{
				while ( 1 )
				{
					printf("請輸入指令:");
					RPC_CSTR Temp[16];
					scanf("%s",&Temp);
					SendMessageEx(hwBinding,(RPC_CSTR)Temp);
					int Add1,Add2,Sum;
					printf("請輸入2個任意整數:");
					scanf("%d %d",&Add1,&Add2);
					Sum = Add(hwBinding,Add1,Add2);
					printf("Sum = %d",Sum);
				}
		
		Hello(hwBinding,(RPC_CSTR)("Thank u for use it"));
	}  
	RpcExcept(1){  
		printf("Runtime reported exception:%d,except=%d\n",GetLastError(),RpcExceptionCode());
	}  
	RpcEndExcept  
		status = RpcBindingFree(&hwBinding);
	RpcStringFree(&szStringBinding);  
 

	if (status){  
		printf("Bind free failed\n");  
		exit(status);}  
	return 0;  
}  
void* __RPC_USER midl_user_allocate(size_t size){  
	return malloc(size);  
}  

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章