<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    用戶自定義結構數據與VARIANT轉換 .

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    用戶自定義結構數據與VARIANT轉換

    cheungmine

    將用戶自定義的C結構數據存儲成VARIANT類型,需要時再將VARIANT類型轉為用戶自定義的結構數據,有十分現實的意義,既然我們不想為這樣的結構數據寫一個COM包裝類。雖然有很多方法和手段生成這樣的VARIANT,但是,多數時候可能需要一個更加簡單的,靈活的方法。我在做遠程過程調用的C接口時,忽然聯想到,既然RPC可以把任何數據以字節的形式發送,那么,就可以利用這個機制,把結構打包成字節數組。而字節數據是可以很方便地存儲在VARIANT中。

     

    這個過程是廣為人知的,但是,真正把結構列集成字節數組,如果不想使用某些標稱的序列化的方法,而全部自己寫,的確要費一番功夫。不是

    技術有多難,是很繁瑣。我把前2年寫的代碼翻出來,簡單調用一下,就有了這篇文章。采用我的方法,C/C++程序員可以把自己定義的結構放到VARIANT、CComVariant、COleVariant等各種VARIANT中,也可以反向轉換。而VARIANT是可以很方便地在COM接口中傳遞。這樣,就多了一種在自動化COM接口中傳遞自定義結構的手段。

     

    不多說廢話,全部內容見下面的代碼,我還會上傳整個工程。

    struct2variant.cpp 如下:

     

    [cpp] view plaincopyprint?
    1. ///////////////////////////////////////////////////////////////////////   
    2. // struct2variant.cpp   
    3. // cheungmine@gmail.com   
    4. // 2010-6   
    5. // 下面的程序演示了如何在用戶自定義的結構和VARIANT類型之間轉換   
    6. // 保留所有權利   
    7. //   
    8. #include "stdafx.h"   
    9. #include "rpc/rpcapi.h"   
    10. #include <assert.h>   
    11. #ifdef _DEBUG   
    12. #  pragma comment(lib, "rpc/rpclib/debug/rpclib.lib")   
    13. #else   
    14. #  pragma comment(lib, "rpc/rpclib/release/rpclib.lib")   
    15. #endif   
    16. // 自定義結構標識   
    17. #define MY_STRUCT_ID  101   // 標識結構的任意數字   
    18. typedef struct _PointF  
    19. {  
    20.     double x;  
    21.     double y;  
    22. }PointF;  
    23. // 自定義結構   
    24. typedef struct _MyStruct  
    25. {  
    26.     CHAR      id[32];  
    27.     CHAR      server[130];  
    28.     CHAR      instance[10];  
    29.     CHAR      userid[32];  
    30.     BOOL      isdraw;  
    31.     ULONG     token;  
    32.     LONG      timeout;  
    33.     LONG      keepalive;  
    34.     LONG      reserved;  
    35.     BOOL      status;  
    36.     LONG      capacity;  
    37.     LONG volatile counter;  
    38.     // 說明如何保存變長數組   
    39.     SHORT     numPts;  
    40.     PointF   *ptArray;    
    41. }MyStruct;  
    42. void PrintfMyStruct(const char *desc, MyStruct *data)  
    43. {  
    44.     printf("==========%s==========/n", desc);  
    45.     printf("id=%s/n", data->id);  
    46.     printf("server=%s/n", data->server);  
    47.     printf("instance=%s/n", data->instance);  
    48.     printf("userid=%s/n", data->userid);  
    49.     printf("isdraw=%d/n", data->isdraw);  
    50.     printf("token=%d/n", data->token);  
    51.     printf("timeout=%d/n", data->timeout);  
    52.     printf("keepalive=%d/n", data->keepalive);  
    53.     printf("reserved=%d/n", data->reserved);  
    54.     printf("status=%d/n", data->status);  
    55.     printf("capacity=%d/n", data->capacity);  
    56.     printf("counter=%d/n", data->counter);  
    57.     printf("numPts=%d/n", data->numPts);  
    58.     for(int i=0; i<data->numPts; i++)  
    59.         printf("ptArray[%d]= (x=%.3lf,     y=%.3lf)/n", i, data->ptArray[i].x, data->ptArray[i].y);  
    60. }  
    61. static HRESULT CreateStreamFromBytes(BYTE *inBytes, DWORD cbSize, IStream **ppStm)  
    62. {  
    63.     HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, 0);  
    64.     ATLASSERT(hGlobal);  
    65.     if (!hGlobal)  
    66.         return E_OUTOFMEMORY;  
    67.       
    68.     CComPtr<IStream> spStm;  
    69.     HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &spStm);  
    70.     ATLASSERT(hr == S_OK);  
    71.     if (hr != S_OK || spStm == 0){  
    72.         GlobalFree(hGlobal);  
    73.         return hr;  
    74.     }  
    75.       
    76.     ULONG  ulWritten = 0;  
    77.     hr = spStm->Write(inBytes, cbSize, &ulWritten);  
    78.     if (hr != S_OK || ulWritten != cbSize)  
    79.         return E_FAIL;  
    80.     return spStm.CopyTo(ppStm);  
    81. }  
    82. ////////////////////////////////////////////////////////////////////   
    83. // 列集自定義數據到VARIANT   
    84. //   
    85. static void MarshallMyStruct(MyStruct *inData, VARIANT *outVar)  
    86. {  
    87.     assert(inData && outVar);  
    88.     rpc_invoke_descriptor  inv  = {0};  
    89.     rpc_invoke_init(&inv, MY_STRUCT_ID, 14);    // 14個參數   
    90.     // 下面每個結構成員參數都需要按次序綁定   
    91.     rpc_invoke_bind_param(&inv,   
    92.                 0,                    /* 結構成員參數索引0-based */  
    93.                 RPCT_STRING,          /* 指明字符串數組類型 */  
    94.                 (void*)inData->id,     /* 指向實際數據的指針 */  
    95.                 strlen(inData->id)+1, /* 只需要保存有效的數據 */  
    96.                 0                     /*0 表示我們不具有id的所有權(不負責釋放內存) */  
    97.             );  
    98.     rpc_invoke_bind_param(&inv,   
    99.                 1,  
    100.                 RPCT_STRING,  
    101.                 (void*)inData->server,  
    102.                 strlen(inData->server)+1,  
    103.                 0  
    104.             );  
    105.     rpc_invoke_bind_param(&inv,   
    106.                 2,  
    107.                 RPCT_STRING,  
    108.                 (void*)inData->instance,  
    109.                 strlen(inData->instance)+1,  
    110.                 0  
    111.             );  
    112.     rpc_invoke_bind_param(&inv,   
    113.                 3,  
    114.                 RPCT_STRING,  
    115.                 (void*)inData->userid,  
    116.                 strlen(inData->userid)+1,  
    117.                 0  
    118.             );  
    119.     rpc_invoke_bind_param(&inv,   
    120.                 4,  
    121.                 RPCT_BOOL,  
    122.                 (void*) &inData->isdraw,  
    123.                 0,  /* 不是數組, 為0 */  
    124.                 0  
    125.             );  
    126.     rpc_invoke_bind_param(&inv,   
    127.                 5,  
    128.                 RPCT_ULONG,  
    129.                 (void*) &inData->token,  
    130.                 0,  
    131.                 0  
    132.             );  
    133.     rpc_invoke_bind_param(&inv,   
    134.                 6,  
    135.                 RPCT_LONG,  
    136.                 (void*) &inData->timeout,  
    137.                 0,  
    138.                 0  
    139.             );  
    140.     rpc_invoke_bind_param(&inv,   
    141.                 7,  
    142.                 RPCT_LONG,  
    143.                 (void*) &inData->keepalive,  
    144.                 0,  
    145.                 0  
    146.             );  
    147.     rpc_invoke_bind_param(&inv,   
    148.                 8,  
    149.                 RPCT_LONG,  
    150.                 (void*) &inData->reserved,  
    151.                 0,  
    152.                 0  
    153.             );  
    154.     rpc_invoke_bind_param(&inv,   
    155.                 9,  
    156.                 RPCT_BOOL,  
    157.                 (void*) &inData->status,  
    158.                 0,  
    159.                 0  
    160.             );  
    161.     rpc_invoke_bind_param(&inv,   
    162.                 10,  
    163.                 RPCT_LONG,  
    164.                 (void*) &inData->capacity,  
    165.                 0,  
    166.                 0  
    167.             );  
    168.     rpc_invoke_bind_param(&inv,   
    169.                 11,  
    170.                 RPCT_LONG,  
    171.                 (void*) &inData->counter,  
    172.                 0,  
    173.                 0  
    174.             );  
    175.     rpc_invoke_bind_param(&inv,   
    176.                 12,  
    177.                 RPCT_SHORT,  
    178.                 (void*) &inData->numPts,  
    179.                 0,  
    180.                 0  
    181.             );  
    182.     rpc_invoke_bind_param(&inv,   
    183.                 13,  
    184.                 RPCT_DOUBLE,    /* 簡單結構的成員類型 */  
    185.                 (void*) inData->ptArray, /* 內存結構=[x1,y1,x2,y2,...,xn,yn], 千萬不可寫成:(void*) &inData->ptArray */  
    186.                 inData->numPts * (sizeof(PointF)/sizeof(double)), /* double類型成員的數目=點數x2 */  
    187.                 0  
    188.             );  
    189.     /* 計算調用消息的字節總數 */  
    190.     dword_t cbOut = rpc_invoke_get_size(&inv);  
    191.     char *outBuf = (char*) malloc(cbOut);  
    192.       
    193.     /* 列集全部數據到totalBuf中 */  
    194.     rpc_invoke_marshal(&inv, outBuf, cbOut);  
    195.     //////////////////////////////////////////////////////////   
    196.     // 到此,我們已經在outBuf中保存了結構的全部數據,    
    197.     // 下面把數據轉換成IStream進而轉換成VARIANT   
    198.     CComPtr<IStream> spStm;  
    199.     CreateStreamFromBytes((BYTE*)outBuf, cbOut, &spStm);  
    200.     VariantInit(outVar);  
    201.     outVar->vt = VT_UNKNOWN;  
    202.     outVar->punkVal = (IUnknown*) spStm.Detach();  
    203.     free(outBuf);  
    204.     rpc_invoke_clear_all(&inv);  
    205. }  
    206. ////////////////////////////////////////////////////////////////////   
    207. // 散集VARIANT到自定義數據   
    208. //   
    209. static void UnmarshallMyStruct(VARIANT *inVar, MyStruct *outData)  
    210. {  
    211.     assert(inVar && outData);  
    212.     assert(inVar->vt==VT_UNKNOWN && inVar->punkVal);  
    213.     HGLOBAL  hGlobal = 0;  
    214.     HRESULT hr = GetHGlobalFromStream((IStream*)inVar->punkVal, &hGlobal);  
    215.     assert(hr==S_OK);  
    216.     size_t  cbData = GlobalSize(hGlobal);  
    217.     char   *pbData = (char*) GlobalLock(hGlobal);  
    218.     char   *rpcHdr = pbData;  
    219.     assert(cbData >= RPC_INVOKE_HEADER_SIZE);  
    220.     assert(rpcHdr[0]=='R' && rpcHdr[1]=='C');  
    221.     rpc_invoke_descriptor  inv={0};  
    222.     rpc_invoke_init(&inv, 0, 0);  
    223.     inv.encPkg = rpcHdr[2];  
    224.     inv.encHdr = rpcHdr[3];  
    225.     assert (inv.encHdr == 0);  
    226.     inv.ordinal = word_ntoh(*((word_t*)(rpcHdr+20)));               // 方法序號: MY_STRUCT_ID   
    227.     assert(inv.ordinal == MY_STRUCT_ID);  
    228.     inv.invToken = dword_ntoh(*((dword_t*)(rpcHdr+4)));             // 用戶標識    
    229.     inv.totalBytes = dword_ntoh(*((dword_t*)(rpcHdr+8)));           // 總消息字節數(也許是壓縮的)   
    230.     inv.bitsFlag = word_ntoh(*((word_t*)(rpcHdr+12)));              // 標志      
    231.     inv.bigEndian = GET_BIT(inv.bitsFlag, RPC_BIGENDIAN_BIT);       // 客戶方列集的字節次序   
    232.     inv.reserved = word_ntoh(*((word_t*)(rpcHdr+14)));              // 保留值   
    233.     inv.result = dword_ntoh(*((dword_t*)(rpcHdr+16)));              // 返回值   
    234.     inv.num_params = word_ntoh(*((word_t*)(rpcHdr+22)));            // 參數數目   
    235.     rpc_invoke_error  err={0};  
    236.     rpc_invoke_unmarshal(&inv, rpcHdr, inv.totalBytes, &inv.params_list, &inv.num_params, &err);  
    237.           
    238.     GlobalUnlock(hGlobal);  
    239.     strncpy_s(outData->id, sizeof(outData->id), (char*) inv.params_list[0].param_bytes, sizeof(outData->id)-1);  
    240.     strncpy_s(outData->server, sizeof(outData->server), (char*) inv.params_list[1].param_bytes, sizeof(outData->server)-1);  
    241.     strncpy_s(outData->instance, sizeof(outData->instance), (char*) inv.params_list[2].param_bytes, sizeof(outData->instance)-1);  
    242.     strncpy_s(outData->userid, sizeof(outData->userid), (char*) inv.params_list[3].param_bytes, sizeof(outData->userid)-1);  
    243.     outData->isdraw = PARAMVALUE(inv.params_list, 4, BOOL);  
    244.     outData->token = PARAMVALUE(inv.params_list, 5, ULONG);  
    245.     outData->timeout = PARAMVALUE(inv.params_list, 6, LONG);  
    246.     outData->keepalive = PARAMVALUE(inv.params_list, 7, LONG);  
    247.     outData->reserved = PARAMVALUE(inv.params_list, 8, LONG);  
    248.     outData->status = PARAMVALUE(inv.params_list, 9, BOOL);  
    249.     outData->capacity = PARAMVALUE(inv.params_list, 10, LONG);  
    250.     outData->counter = PARAMVALUE(inv.params_list, 11, LONG);  
    251.     outData->numPts = PARAMVALUE(inv.params_list, 12, SHORT);  
    252.     // 為輸出分配 ptArray   
    253.     outData->ptArray = (PointF*) malloc(sizeof(PointF)*outData->numPts);  
    254.     memcpy(outData->ptArray, inv.params_list[13].param_bytes, sizeof(PointF)*outData->numPts);  
    255.     rpc_invoke_clear_all(&inv);  
    256. }  
    257. int main(int argc, CHAR* argv[])  
    258. {  
    259.     MyStruct     data, data2;  
    260.     CComVariant  var;   // 這個var 可以存儲在任何需要使用到的地方   
    261.     // 初始化結構data   
    262.     strcpy_s(data.id, sizeof(data.id), "13890");  
    263.     strcpy_s(data.server, sizeof(data.server), "localhost");  
    264.     strcpy_s(data.instance, sizeof(data.instance), "port:6755");  
    265.     strcpy_s(data.userid, sizeof(data.userid), "cheungmine");  
    266.     data.isdraw = 1;  
    267.     data.token = 54321;  
    268.     data.timeout = 3000;  
    269.     data.keepalive = 6500;  
    270.     data.reserved=0;  
    271.     data.status = 0;  
    272.     data.capacity = 4096;  
    273.     data.counter = 99;  
    274.     data.numPts = 16;  
    275.     data.ptArray = (PointF*) malloc(data.numPts*sizeof(PointF));  
    276.     for(int i=0; i<data.numPts; i++){  
    277.         data.ptArray[i].x = 100+i;  
    278.         data.ptArray[i].y = 200+i;  
    279.     }  
    280.     PrintfMyStruct("input MyStruct", &data);  
    281.       
    282.     // 用戶的結構轉換為VARIANT: data=>var   
    283.     MarshallMyStruct(&data, &var);  
    284.     free(data.ptArray);  
    285.     // ...使用var   
    286.     // VARIANT轉為用戶的結構: var=>data   
    287.     UnmarshallMyStruct(&var, &data2);  
    288.     PrintfMyStruct("output MyStruct", &data2);  
    289.     free(data2.ptArray);  
    290. }  

     

     

    其中:rpcapi.h可以參考如下:

    [cpp] view plaincopyprint?
    1. /** 
    2.  * rpcapi.h -cheungmine@gmail.com 
    3.  * all rights reserved 2009 
    4.  */  
    5. #ifndef _RPCAPI_H__   
    6. #define _RPCAPI_H__   
    7. #include <winsock2.h>   
    8. #pragma comment(lib, "ws2_32.lib")   
    9. #include <process.h>  /* _beginthreadex, _endthread */   
    10. #include "../rc4/unistd.h"   
    11. #include "../rc4/md5.h"   
    12. #include "../rc4/rc4.h"   
    13. #include "rpctype.h"   
    14. #include "rpcerr.h"   
    15. #ifdef __cplusplus   
    16. extern "C" {  
    17. #endif   
    18. static BOOL  _rpc_is_bigendian = (('4321'>>24)=='1');  
    19. #define PARAMVALUE(pl,i,type)     ((type)(*((type*) pl[i].param_bytes)))   
    20. typedef enum  
    21. {  
    22.     RPC_ENCHEADER_BIT  = 0,  
    23.     RPC_ENCPACKAGE_BIT  = 1,  
    24.     RPC_BIGENDIAN_BIT  = 7  
    25. }RPC_BITFLAG_ENUM;  
    26. /** 
    27.  * param descriptor  
    28.  */  
    29. #define RPC_PARAM_HEADER_SIZE  16   
    30. typedef struct _rpc_param_descriptor  
    31. {  
    32.     word_t      param_type;         // 參數類型:變量類型或結構類型   
    33.     word_t      size_type;          // 參數類型尺寸字節   
    34.     size_t      array_size;         // 數組元素數目: 0 不是數組; >0數組   
    35.       
    36.     size_t      param_size;         // 參數數據字節數=參數類型尺寸字節*元素數目   
    37.     void       *param_bytes;        // 指向參數數據的指針的引用, 不復制數據   
    38.     BOOL        is_owner;           // 是否擁有數據. 如果為TRUE, 需要free(param_bytes)   
    39. }rpc_param_descriptor;  
    40. /** 
    41.  * invoke descriptor  
    42.  */  
    43. #define RPC_INVOKE_HEADER_SIZE  24      /* 不可以更改 */   
    44. typedef struct _rpc_invoke_descriptor  
    45. {  
    46.     /* 24字節頭 + 內容 
    47.      *  ['RCmn'(4)|用戶標識(4)|總消息字節(4)|標志(2)| 保留(2)|原始字節數(4)|方法序號(2)|參數數目(2)] 
    48.      */  
    49.     dword_t                totalBytes;  // 總消息字節4   
    50.     word_t                 bitsFlag;    // 標志位2: [7=BigEndian]   
    51.     word_t                 reserved;    // 保留2   
    52.     dword_t                result;      // 返回值   
    53.     // 內部值, 調用時,需要列集在bitsFlag中   
    54.     dword_t                invToken;  
    55.     byte                   bigEndian;  
    56.     byte                   encHdr;  
    57.     byte                   encPkg;  
    58.     // 如果壓縮或加密, 從以下位置內容開始      
    59.     ushort                 ordinal;     // 方法序號2       
    60.     ushort                 num_params;  // 參數數目   
    61.     rpc_param_descriptor  *params_list; // 參數列表   
    62.     // 做為輸入時, 存放臨時值   
    63.     //   
    64.     char                  *pbBuf;  
    65.     union{  
    66.         char               bVal;  
    67.         long               lVal;  
    68.         short              sVal;  
    69.         float              fVal;  
    70.         double             dVal;  
    71.         __int64            llVal;  
    72.     };  
    73. }rpc_invoke_descriptor;  
    74. /** 
    75.  * connection descriptor 
    76.  */  
    77. typedef struct _rpc_connection_descriptor  
    78. {  
    79.     BOOL               is_bigendian;    // 字節順序   
    80.     dword_t            token;           // 調用標識   
    81.     dword_t            timeout;         // 超時   
    82.     byte               enc_hdr;         // 頭加密標志   
    83.     byte               enc_pkg;         // 參數包加密標志   
    84.     SOCKET             stream;          // SOCKET 連接   
    85.     char               host[130];       // 主機名或IP地址   
    86.     char               port[6];         // 端口號   
    87.       
    88.     rpc_invoke_error   last_err;        // 最近的錯誤   
    89.     char               buffer[RPC_BUFFSIZE];  // 網絡傳輸緩沖區   
    90. }rpc_connection_descriptor;  
    91. /*============================================================================= 
    92.                               Private Functions 
    93.                  host byte order and network byte order transform 
    94. =============================================================================*/  
    95. static int SafeStringSize(const char* psz)  
    96. {  
    97.     return (int)(psz? (strlen(psz)+1):0);  
    98. }  
    99. /** 
    100.  * More fast than swap_bytes(...) for handle word and dword type 
    101.  */  
    102. #define swap_word_type(x)  ((WORD)(((((WORD)(x))&0x00ff)<<8)|((((WORD)(x))&0xff00)>>8)))   
    103. #define swap_dword_type(x)  ((DWORD)(((((DWORD)(x))&0xff000000)>>24)|((((DWORD)(x))&0x00ff0000)>>8)|((((DWORD)(x))&0x0000ff00)<<8)|((((DWORD)(x))&0x000000ff)<<24)))   
    104. static void swap_bytes(void *wordP, size_t cbSize /*must be 2, 4, 8 */)  
    105. {  
    106.     size_t   i;  
    107.     byte     t;  
    108.     for(i=0; i<cbSize/2; i++){  
    109.         t = ((byte *) wordP)[i];  
    110.         ((byte *)wordP)[i] = ((byte *) wordP)[cbSize-i-1];  
    111.         ((byte *) wordP)[cbSize-i-1] = t;  
    112.     }  
    113. }  
    114. static dword_t  dword_hton(dword_t host)  
    115. {  
    116.     if (!_rpc_is_bigendian)  
    117.         host = swap_dword_type(host);  
    118.     return  host;  
    119. }  
    120. static dword_t  dword_ntoh(dword_t net)  
    121. {  
    122.     if (!_rpc_is_bigendian)  
    123.         net = swap_dword_type(net);  
    124.     return  net;  
    125. }  
    126. static word_t   word_hton(word_t host)  
    127. {  
    128.     if (!_rpc_is_bigendian)  
    129.         host = swap_word_type(host);  
    130.     return  host;  
    131. }  
    132. static word_t   word_ntoh(word_t net)  
    133. {  
    134.     if (!_rpc_is_bigendian)  
    135.         net = swap_word_type(net);  
    136.     return  net;  
    137. }  
    138. static qword_t  qword_hton(qword_t host)  
    139. {  
    140.     if (!_rpc_is_bigendian)  
    141.         swap_bytes(&host, sizeof(qword_t));  
    142.     return  host;  
    143. }  
    144. static qword_t  qword_ntoh(qword_t net)  
    145. {  
    146.     if (!_rpc_is_bigendian)  
    147.         swap_bytes(&net, sizeof(qword_t));  
    148.     return  net;  
    149. }  
    150. static double   double_hton(double host)  
    151. {  
    152.     if (!_rpc_is_bigendian)  
    153.         swap_bytes(&host, sizeof(qword_t));  
    154.     return  host;  
    155. }  
    156. static double   double_ntoh(double net)  
    157. {  
    158.     if (!_rpc_is_bigendian)  
    159.         swap_bytes(&net, sizeof(qword_t));  
    160.     return  net;  
    161. }  
    162. static float    float_hton(float host)  
    163. {  
    164.     if (!_rpc_is_bigendian)  
    165.         swap_bytes(&host, sizeof(dword_t));  
    166.     return  host;  
    167. }  
    168. static float    float_ntoh(float net)  
    169. {  
    170.     if (!_rpc_is_bigendian)  
    171.         swap_bytes(&net, sizeof(dword_t));  
    172.     return  net;  
    173. }  
    174. /*============================================================================= 
    175.                               Private Functions 
    176.                            socket helper functions 
    177. =============================================================================*/  
    178. static int setbufsize(SOCKET s, int rcvlen /*RPC_BUFFSIZE*/int sndlen /*RPC_BUFFSIZE*/)  
    179. {  
    180.     int rcv, snd;  
    181.     int rcvl = (intsizeof(int);  
    182.     int sndl = rcvl;  
    183.     if ( getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rcv, &rcvl)==SOCKET_ERROR ||  
    184.          getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&snd, &sndl)==SOCKET_ERROR )  
    185.         return SOCKET_ERROR;  
    186.       
    187.     if(rcv < rcvlen){  
    188.         rcv = rcvlen;  
    189.         rcvl = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rcv, rcvl);  
    190.         assert(rcvl==0);  
    191.     }  
    192.       
    193.     if(snd < sndlen){  
    194.         snd = sndlen;     
    195.         sndl = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&snd, sndl);  
    196.         assert(sndl==0);  
    197.     }  
    198.     return 0;  
    199. }  
    200. static int sendmsg(SOCKET s, const char* msgbuf, int msglen, int flags)  
    201. {  
    202.     int ret;  
    203.     int offset = 0;  
    204.     int left = msglen;    
    205.     while (left > 0) {  
    206.         ret = send(s, &msgbuf[offset], left, flags);  
    207.         if (ret==SOCKET_ERROR || ret==0)  
    208.             return ret;       
    209.         left -= ret;  
    210.         offset += ret;  
    211.     }  
    212.     assert(offset==msglen);  
    213.     return offset;  
    214. }  
    215. static int recvmsg(SOCKET s, char* msgbuf, int buflen, int flags)  
    216. {  
    217.     int     ret;  
    218.     int     offset = 0;  
    219.     int     left = buflen;    
    220.     while (left > 0){  
    221.         ret = recv(s, &msgbuf[offset], left, flags);  
    222.         if (ret==SOCKET_ERROR || ret==0)  
    223.             return ret;  
    224.         offset += ret;  
    225.         left -= ret;  
    226.     }  
    227.     assert(offset==buflen);  
    228.     return offset;  
    229. }  
    230. static BOOL sendbulk(SOCKET s, const char* data, int dataSize, int flags, int maxmsg)  
    231. {  
    232.     int send, ret;  
    233.     int offset = 0;  
    234.     int left = dataSize;  
    235.     while (left > 0) {  
    236.         send = left>maxmsg? maxmsg:left;  
    237.         ret = sendmsg(s, &data[offset], send, flags);  
    238.         if (ret != send)  
    239.             return FALSE;  
    240.         offset += ret;  
    241.         left -= ret;  
    242.     }  
    243.     return TRUE;  
    244. }  
    245. static BOOL recvbulk(SOCKET s, char* buf, int recvlen, int flags, int maxmsg)  
    246. {  
    247.     int  recv, ret;  
    248.     int  offset = 0;  
    249.     int  left = recvlen;  
    250.     while (left > 0){  
    251.         recv = left>maxmsg? maxmsg:left;  
    252.         ret = recvmsg(s, &buf[offset], recv, flags);  
    253.         if (ret != recv)  
    254.             return FALSE;  
    255.         offset += ret;  
    256.         left -= ret;  
    257.     }  
    258.     return TRUE;  
    259. }  
    260. static LPCSTR errmsg(DWORD dwCode, LPSTR lpszMsgBuf, DWORD dwMsgBufBytes)  
    261. {  
    262.     FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,  
    263.             NULL, dwCode, 0, /* Default language */  
    264.             lpszMsgBuf,  
    265.             dwMsgBufBytes,  
    266.             NULL);  
    267.     return lpszMsgBuf;  
    268. }  
    269. static void rpc_error_clear(rpc_invoke_error *err)  
    270. {  
    271.     err->err_type = RPC_NO_ERROR;  
    272.     err->err_code = 0;  
    273.     *err->err_source = 0;  
    274.     *err->err_detail = 0;  
    275. }  
    276. // [RESM(4)|總消息字節(4)|err_type(2)|err_code(2)|err_source_size(2)|err_source_string|err_detail_size(2)|err_detail_string]   
    277. static BOOL rpc_error_short_msg(SOCKET s, char *buf, int size, rpc_invoke_error *err)  
    278. {  
    279.     int pos = 0;  
    280.     word_t w;  
    281.     ushort err_source_size = (ushort)strlen(err->err_source)+1;  
    282.     ushort err_detail_size = (ushort)strlen(err->err_detail)+1;  
    283.     ulong  msglen = 4+4+2+2+2+err_source_size+2+err_detail_size;  
    284.     *buf = 0;  
    285.     assert((ulong)size>=msglen);  
    286.     buf[pos++] = 'R';  
    287.     buf[pos++] = 'E';  
    288.     buf[pos++] = 'S';  
    289.     buf[pos++] = 'M';  
    290.       
    291.     msglen = dword_hton(msglen);  
    292.     memcpy(buf+pos, &msglen, 4);  
    293.     pos += 4;  
    294.     w = word_hton((word_t)err->err_type);  
    295.     memcpy(buf+pos, &w, 2);  
    296.     pos += 2;  
    297.     w = word_hton((word_t)err->err_code);  
    298.     memcpy(buf+pos, &w, 2);  
    299.     pos += 2;  
    300.     w = word_hton((word_t)err_source_size);  
    301.     memcpy(buf+pos, &w, 2);  
    302.     pos += 2;     
    303.     memcpy(buf+pos, err->err_source, err_source_size);  
    304.     pos += err_source_size;  
    305.     w = word_hton((word_t)err_detail_size);  
    306.     memcpy(buf+pos, &w, 2);  
    307.     pos += 2;  
    308.     memcpy(buf+pos, err->err_detail, err_detail_size);  
    309.     pos += err_detail_size;  
    310.     assert((ulong)pos == dword_ntoh(msglen));  
    311.     if (pos == (ulong)sendmsg(s, buf, pos, 0))  
    312.         return TRUE;  
    313.     err->err_type = RPC_SOCKET_ERROR;  
    314.     err->err_code = WSAGetLastError();  
    315.     *err->err_source = 0;  
    316.     errmsg(err->err_code, err->err_detail, RPC_ERROR_STRING_LEN);  
    317.       
    318.     return FALSE;  
    319. }  
    320. static void debug_out(const char *debug_file, const char *fmt, ...)  
    321. {  
    322. #ifdef _DEBUG   
    323.     FILE *fp = 0;  
    324.     va_list ap;  
    325.       
    326.     fopen_s(&fp, debug_file, "a+");  
    327.     assert(fp);  
    328.       
    329.     va_start(ap, fmt);  
    330.     vfprintf(fp, fmt, ap);  
    331.     va_end(ap);  
    332.     fclose(fp);  
    333. #endif   
    334. }  
    335. /*============================================================================ 
    336.                        RPC PUBLIC FUNCTIONS 
    337.  ============================================================================*/  
    338. /** 
    339.  * rpc_throw_error 
    340.  */  
    341. RPCRESULT rpc_throw_error(RPC_ERROR_TYPE err_type, LONG err_code, const char* err_source, rpc_invoke_error *err);  
    342. /** 
    343.  * rpc_invoke_free 
    344.  *   創建RPC調用描述符 
    345.  */  
    346. rpc_invoke_descriptor* rpc_invoke_create(rpc_invoke_descriptor **inv, ushort ordinal, ushort num_params);  
    347. /** 
    348.  * rpc_invoke_init 
    349.  *   初始化RPC調用描述符 
    350.  */  
    351. rpc_invoke_descriptor *  
    352. rpc_invoke_init(rpc_invoke_descriptor *inv, ushort ordinal, ushort num_params);  
    353. /** 
    354.  * rpc_invoke_clear_all 
    355.  *   清除RPC調用描述符, 此后RPC調用描述符可以重新綁定變量 
    356.  */  
    357. void rpc_invoke_clear_all(rpc_invoke_descriptor *inv);  
    358. /** 
    359.  * rpc_invoke_free 
    360.  *   刪除RPC調用描述符, 此后RPC調用描述符將不可用 
    361.  */  
    362. void rpc_invoke_free(rpc_invoke_descriptor *inv);  
    363. /** 
    364.  * rpc_invoke_set_param 
    365.  *   設置指定的參數, 返回參數指針 
    366.  */  
    367. rpc_param_descriptor* rpc_invoke_set_param(rpc_invoke_descriptor *inv, ushort id, word_t type);  
    368. /** 
    369.  * rpc_param_clear 
    370.  *   清除參數內容 
    371.  */  
    372. void rpc_param_clear(rpc_param_descriptor *param);  
    373. /** 
    374.  * rpc_param_free_list 
    375.  *   清除參數列表內容 
    376.  */  
    377. void rpc_param_free_list(rpc_param_descriptor *param_list, word_t num_params);  
    378. /** 
    379.  * rpc_connection_create 
    380.  *   創建RPC連接 
    381.  */  
    382. RPCRESULT rpc_connection_create(rpc_connection_descriptor **conn, const char *host, const char *port, long rcvtimeo, rpc_invoke_error *err);  
    383. /** 
    384.  * rpc_connection_free 
    385.  *   清除RPC連接 
    386.  */  
    387. void rpc_connection_free(rpc_connection_descriptor *conn);  
    388. /** 
    389.  * rpc_connection_set 
    390.  *   設置RPC連接的屬性 
    391.  */  
    392. void rpc_connection_set(rpc_connection_descriptor *conn, dword_t token, dword_t timeout, byte encheader, byte encpackage);  
    393. /** 
    394.  * rpc_connection_free 
    395.  *   設置輸入的參數, 返回參數指針 
    396.  */  
    397. rpc_param_descriptor* rpc_invoke_bind_param(rpc_invoke_descriptor *inv, ushort id, word_t type, void *vaddr, size_t array_size, BOOL is_owner);  
    398. /** 
    399.  * rpc_connection_free 
    400.  *   計算參數字節總數 
    401.  */  
    402. dword_t rpc_param_get_size(rpc_param_descriptor *param);  
    403. /** 
    404.  * rpc_connection_free 
    405.  *   計算調用消息的字節總數 
    406.  */  
    407. dword_t rpc_invoke_get_size(rpc_invoke_descriptor *inv);  
    408. /** 
    409.  * rpc_invoke_marshal 
    410.  *   列集全部數據到totalBuf中 
    411.  */  
    412. int rpc_invoke_marshal(rpc_invoke_descriptor *inv, char *totalBuf, int totalSize);  
    413. /** 
    414.  * rpc_invokehdr_unmarshal 
    415.  *   散集調用頭 
    416.  */  
    417. RPCRESULT rpc_invokehdr_unmarshal(SOCKET sClient, dword_t dwToken, char *rpcHdr, int hdrSize, rpc_invoke_descriptor *inv, rpc_invoke_error *err);  
    418. /** 
    419.  * rpc_invoke_unmarshal 
    420.  *   散集數據到參數中 
    421.  */  
    422. RPCRESULT rpc_invoke_unmarshal(rpc_invoke_descriptor *inv,   
    423.                                char                  *totalBuf,   
    424.                                size_t                 totalSize,  
    425.                                rpc_param_descriptor **out_params,  
    426.                                word_t                *num_params,  
    427.                                rpc_invoke_error      *err);  
    428. /** 
    429.  * rpc_param_get_short 
    430.  *   取得短整數參數值 
    431.  */  
    432. void rpc_param_get_short (rpc_param_descriptor *param, SHORT *val);  
    433. /** 
    434.  * rpc_param_get_ushort 
    435.  *   取得短整數參數值 
    436.  */  
    437. void rpc_param_get_ushort (rpc_param_descriptor *param, USHORT *val);  
    438. /** 
    439.  * rpc_param_get_long 
    440.  *   取得整數參數值 
    441.  */  
    442. void rpc_param_get_long (rpc_param_descriptor *param, LONG *val);  
    443. /** 
    444.  * rpc_param_get_ulong 
    445.  *   取得無符號整數參數值 
    446.  */  
    447. void rpc_param_get_ulong (rpc_param_descriptor *param, ULONG *val);  
    448. /** 
    449.  * rpc_param_get_int 
    450.  *   取得整數參數值 
    451.  */  
    452. void rpc_param_get_int (rpc_param_descriptor *param, INT *val);  
    453. /** 
    454.  * rpc_param_get_double 
    455.  *   取得雙精度參數值 
    456.  */  
    457. void rpc_param_get_double (rpc_param_descriptor *param, double *val);  
    458. /** 
    459.  * rpc_invoke_send 
    460.  *   發送數據 
    461.  */  
    462. RPCRESULT rpc_invoke_send(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_error *err);  
    463. /** 
    464.  * rpc_invoke_recv 
    465.  *   接收數據 
    466.  */  
    467. RPCRESULT rpc_invoke_recv(rpc_connection_descriptor *conn, rpc_invoke_descriptor *outv, rpc_invoke_error *err);  
    468. /** 
    469.  * rpc_connection_free 
    470.  *   執行RPC調用 
    471.  */  
    472. RPCRESULT rpc_invoke_execute(rpc_connection_descriptor *conn,   
    473.                              rpc_invoke_descriptor     *inv,   
    474.                              rpc_invoke_descriptor     *outv,   
    475.                              rpc_invoke_error          *err);  
    476. #ifdef __cplusplus   
    477. }  
    478. #endif   
    479. #endif /* _RPCAPI_H__ */  

     

     

    rpcapi.c如下:

    [cpp] view plaincopyprint?
    1. /** 
    2.  * rpcapi.c -cheungmine@gmail.com 
    3.  */  
    4. #include "rpcapi.h"   
    5. // 打開socket   
    6. static RPCRESULT opensocket(SOCKET *pStream, const char *lpszServer, int nPort, rpc_invoke_error *pError)  
    7. {  
    8.     struct sockaddr_in   server;  
    9.     struct hostent      *hp = 0;  
    10.     unsigned int         iAddr;  
    11.       
    12.     *pStream = INVALID_SOCKET;  
    13.     // Parse server host   
    14.     if(inet_addr(lpszServer) == INADDR_NONE){  
    15.         hp = gethostbyname(lpszServer);  
    16.         if(hp==0)  
    17.             return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_HOST, "opensocket()", pError);  
    18.         server.sin_addr.s_addr = *((unsigned long*)hp->h_addr);  
    19.     }  
    20.     else{  
    21.         iAddr = inet_addr(lpszServer);  
    22.         server.sin_addr.s_addr = iAddr;  
    23.       
    24.         // too slow to use gethostbyaddr   
    25.     //OLD:  hp = gethostbyaddr((char*)&iAddr, sizeof(iAddr), AF_INET);   
    26.     //OLD:  if(hp==0)   
    27.     //OLD:      return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_HOST, "opensocket()", pError);   
    28.     //OLD:  server.sin_addr.s_addr = *((unsigned long*)hp->h_addr);   
    29.     }  
    30.     server.sin_family = AF_INET;  
    31.     server.sin_port = htons((u_short)nPort);  
    32.     // Create a new socket and attempt to connect to server   
    33.     (*pStream) = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
    34.     if ((*pStream) == INVALID_SOCKET)  
    35.         return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "socket()", pError);  
    36.     // Make a connection to the server   
    37.     if (connect((*pStream), (struct sockaddr *) &server, sizeof(server))==SOCKET_ERROR){  
    38.         closesocket( *pStream );  
    39.         *pStream = INVALID_SOCKET;  
    40.         return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "connect()", pError);  
    41.     }  
    42.     setbufsize(*pStream, RPC_BUFFSIZE, RPC_BUFFSIZE);  
    43.     return RPC_SUCCESS;  
    44. }  
    45. // 列集參數   
    46. static int rpc_param_marshal(rpc_param_descriptor *param, char *buf)  
    47. {  
    48.     word_t   w;  
    49.     dword_t  dw;  
    50.     int pos = 0;  
    51.     // 參數頭RPC_PARAM_HEADER_SIZE字節:   
    52.     //   [參數類型(2)|類型字節(2)|數組元素數目(4)|參數數據字節數(4)|參數成員數(2)=0|保留(2)=0]   
    53.     w = word_hton(param->param_type);  
    54.     memcpy(buf+pos, &w, 2);  
    55.     pos += 2;  
    56.     w = word_hton(param->size_type);  
    57.     memcpy(buf+pos, &w, 2);  
    58.     pos += 2;  
    59.       
    60.     dw = dword_hton((dword_t)param->array_size);  
    61.     memcpy(buf+pos, &dw, 4);  
    62.     pos += 4;  
    63.     dw = dword_hton((dword_t)param->param_size);  
    64.     memcpy(buf+pos, &dw, 4);  
    65.     pos += 4;  
    66.     w = 0;  
    67.     memcpy(buf+pos, &w, 2);  
    68.     pos += 2;  
    69.     w = 0;  
    70.     memcpy(buf+pos, &w, 2);  
    71.     pos += 2;  
    72.     // 參數的數據   
    73.     memcpy(buf+pos, param->param_bytes, param->param_size);  
    74.     pos += (int)param->param_size;  
    75.     return pos;  
    76. }  
    77. // 散集參數   
    78. // 參數頭RPC_PARAM_HEADER_SIZE字節:   
    79. //   [參數類型(2)|類型字節(2)|數組元素數目(4)|參數數據字節數(4)|參數成員數(2)|保留(2)=0]   
    80. static size_t rpc_param_unmarshal(BOOL marshal_bigendian, rpc_param_descriptor *param, char *buf)  
    81. {  
    82.     byte   *pcb;  
    83.     size_t  i;  
    84.     size_t  pos = 0;  
    85.     assert(param->array_size==0||param->array_size==param->param_size/param->size_type);  
    86.     // 參數類型   
    87.     param->param_type = word_ntoh(*((word_t*)(buf+pos)));  
    88.     pos += 2;  
    89.     param->size_type = word_ntoh(*((word_t*)(buf+pos)));  
    90.     pos += 2;  
    91.     param->array_size = dword_ntoh(*((dword_t*)(buf+pos)));  
    92.     pos += 4;  
    93.     param->param_size = dword_ntoh(*((dword_t*)(buf+pos)));  
    94.     pos += 4;  
    95.     // 參數成員   
    96.     pos += 2;  
    97.     // 保留值   
    98.     pos += 2;  
    99.     // 參數字節指針   
    100.     // 這里假設列集方marshal_bigendian和散集方_rpc_is_bigendian的字節次序一致,    
    101.     // 以后要添加代碼處理不一致的情況   
    102.     if (param->param_size==0){  
    103.         param->param_bytes = 0;  
    104.         return pos;  
    105.     }  
    106.     if (param->size_type==1 || marshal_bigendian==_rpc_is_bigendian){  
    107.         param->param_bytes = (void*)(buf+pos);  
    108.         return (pos + param->param_size);  
    109.     }  
    110.       
    111.     // 必須交換字節次序   
    112.     //   
    113.     assert(param->size_type==2||param->size_type==4||param->size_type==8);  
    114.     assert(marshal_bigendian != _rpc_is_bigendian);  
    115.     param->param_bytes = (void*)(buf+pos);  
    116.     pcb = (buf+pos);  
    117.       
    118.     i = param->param_size/param->size_type;  
    119.     while(i-->0){  
    120.         swap_bytes(&pcb[i*param->size_type], param->size_type);  
    121.     }  
    122.     assert(i==-1);  
    123.     return (pos + param->param_size);  
    124. }  
    125. void rpc_param_get_ushort (rpc_param_descriptor *param, USHORT *val)  
    126. {  
    127.     assert(param && param->param_bytes && param->array_size==0 &&   
    128.            param->param_type==RPCT_USHORT && param->size_type==RPC_TYPE_SIZE(RPCT_USHORT));  
    129.       
    130.     *val = *((USHORT*)(param->param_bytes));  
    131. }  
    132. void rpc_param_get_short (rpc_param_descriptor *param, SHORT *val)  
    133. {  
    134.     assert(param && param->param_bytes && param->array_size==0 &&   
    135.            param->param_type==RPCT_SHORT && param->size_type==RPC_TYPE_SIZE(RPCT_SHORT));  
    136.       
    137.     *val = *((SHORT*)(param->param_bytes));  
    138. }  
    139. void rpc_param_get_long (rpc_param_descriptor *param, LONG *val)  
    140. {  
    141.     assert(param && param->param_bytes && param->array_size==0 &&   
    142.            param->param_type==RPCT_LONG && param->size_type==RPC_TYPE_SIZE(RPCT_LONG));  
    143.       
    144.     *val = *((LONG*)(param->param_bytes));  
    145. }  
    146. void rpc_param_get_int (rpc_param_descriptor *param, INT *val)  
    147. {  
    148.     assert(param && param->param_bytes && param->array_size==0 &&   
    149.            param->param_type==RPCT_INT && param->size_type==RPC_TYPE_SIZE(RPCT_INT));  
    150.       
    151.     *val = *((INT*)(param->param_bytes));  
    152. }  
    153. void rpc_param_get_ulong (rpc_param_descriptor *param, ULONG *val)  
    154. {  
    155.     assert(param && param->param_bytes && param->array_size==0 &&   
    156.            param->param_type==RPCT_ULONG && param->size_type==RPC_TYPE_SIZE(RPCT_ULONG));  
    157.       
    158.     *val = *((ULONG*)(param->param_bytes));  
    159. }  
    160. void rpc_param_get_double (rpc_param_descriptor *param, DOUBLE *val)  
    161. {  
    162.     assert(param && param->param_bytes && param->array_size==0 &&   
    163.            param->param_type==RPCT_DOUBLE && param->size_type==RPC_TYPE_SIZE(RPCT_DOUBLE));  
    164.       
    165.     *val = *((DOUBLE*)(param->param_bytes));  
    166. }  
    167. RPCRESULT rpc_invoke_send(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_error *err)  
    168. {  
    169.     BOOL       br;  
    170.     char      *buffer = 0;  
    171.     dword_t    cbTotal = 0;  
    172.       
    173.     cbTotal = rpc_invoke_get_size(inv);  
    174.           
    175.     // 既然<=RPC_BUFFSIZE, 則使用默認的buffer   
    176.     if (cbTotal <= RPC_BUFFSIZE){  
    177.         cbTotal = rpc_invoke_marshal(inv, conn->buffer, cbTotal);  
    178.         assert(cbTotal != -1);  
    179.               
    180.         if (cbTotal != sendmsg(conn->stream, conn->buffer, cbTotal, 0))  
    181.             return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "rpc_invoke_send()", err);  
    182.         else  
    183.             return RPC_SUCCESS;  
    184.     }  
    185.     else {  
    186.         buffer = malloc(cbTotal);  
    187.           
    188.         // 內存分配失敗   
    189.         if (!buffer)  
    190.             return rpc_throw_error(RPC_SYSTEM_ERROR, GetLastError(), "rpc_invoke_send()", err);  
    191.           
    192.         cbTotal = rpc_invoke_marshal(inv, buffer, cbTotal);  
    193.         assert(cbTotal != -1);  
    194.           
    195.         // 發送大塊數據   
    196.         br = sendbulk(conn->stream, buffer, cbTotal, 0, RPC_BUFFSIZE);  
    197.         FREE_S(buffer)  
    198.         if (!br)  
    199.             return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "rpc_invoke_send()", err);  
    200.         else  
    201.             return RPC_SUCCESS;  
    202.     }  
    203. }  
    204. RPCRESULT rpc_invoke_recv(rpc_connection_descriptor *conn, rpc_invoke_descriptor *outv, rpc_invoke_error *err)  
    205. {  
    206.     RPCRESULT  res;  
    207.     // 接收頭   
    208.     res = rpc_invokehdr_unmarshal(conn->stream, conn->token, conn->buffer, RPC_INVOKE_HEADER_SIZE, outv, err);  
    209.     if (RPC_SUCCESS != res)  
    210.         return res;  
    211.     // 驗證token   
    212.     if (conn->token != outv->invToken)  
    213.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "rpc_invoke_recv()", err);  
    214.     // 接收其余全部數據   
    215.     if (outv->totalBytes > RPC_BUFFSIZE){  
    216.         MALLOC_S(outv->pbBuf, outv->totalBytes, char);  
    217.         memcpy(outv->pbBuf, conn->buffer, RPC_INVOKE_HEADER_SIZE);  
    218.     }  
    219.     else{  
    220.         outv->pbBuf = conn->buffer;  
    221.     }  
    222.     assert(outv->pbBuf);  
    223.     if (!recvbulk(conn->stream, outv->pbBuf+RPC_INVOKE_HEADER_SIZE, outv->totalBytes-RPC_INVOKE_HEADER_SIZE, 0, RPC_BUFFSIZE)){  
    224.         if (outv->pbBuf != conn->buffer){  
    225.             FREE_S(outv->pbBuf)  
    226.             outv->pbBuf = 0;  
    227.         }  
    228.         return rpc_throw_error(RPC_USER_ERROR, RPC_NETWORK_ERROR, "rpc_invoke_recv()", err);  
    229.     }  
    230.     if (RPC_SUCCESS != rpc_invoke_unmarshal(outv, outv->pbBuf, outv->totalBytes, &outv->params_list, &outv->num_params, err)){  
    231.         if (outv->pbBuf != conn->buffer){  
    232.             FREE_S(outv->pbBuf)  
    233.             outv->pbBuf = 0;  
    234.         }  
    235.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "rpc_invoke_recv()", err);  
    236.     }  
    237.     return RPC_SUCCESS;  
    238. }  
    239. /*============================================================================= 
    240.                               Public Functions 
    241.                       Remote Procedure Call Impementation 
    242. =============================================================================*/  
    243. rpc_invoke_descriptor*  
    244. rpc_invoke_create(rpc_invoke_descriptor **inv, ushort ordinal, ushort num_params)  
    245. {     
    246.     assert(inv);  
    247.     MALLOC_S(*inv, 1, rpc_invoke_descriptor)  
    248.     assert(*inv);  
    249.       
    250.     (*inv)->bigEndian = _rpc_is_bigendian;  
    251.     (*inv)->ordinal = ordinal;  
    252.     (*inv)->num_params = num_params;  
    253.           
    254.     MALLOC_S((*inv)->params_list, num_params, rpc_param_descriptor)  
    255.           
    256.     return (*inv);  
    257. }  
    258. rpc_invoke_descriptor *  
    259. rpc_invoke_init(rpc_invoke_descriptor *inv, ushort ordinal, ushort num_params)  
    260. {     
    261.     assert(inv);  
    262.     rpc_invoke_clear_all(inv);  
    263.     inv->ordinal = ordinal;  
    264.     inv->num_params = num_params;      
    265.     MALLOC_S(inv->params_list, num_params, rpc_param_descriptor)  
    266.     return inv;  
    267. }  
    268. void rpc_invoke_clear_all(rpc_invoke_descriptor *inv)  
    269. {  
    270.     assert(inv);  
    271.     if (inv->pbBuf && inv->totalBytes>RPC_BUFFSIZE){  
    272.         FREE_S(inv->pbBuf)  
    273.         assert(inv->pbBuf==0);  
    274.     }  
    275.     rpc_param_free_list(inv->params_list, inv->num_params);  
    276.     memset(inv, 0, sizeof(rpc_invoke_descriptor));  
    277.     inv->bigEndian = _rpc_is_bigendian? 1:0;  
    278. }  
    279. void rpc_invoke_free(rpc_invoke_descriptor *inv)  
    280. {  
    281.     rpc_invoke_clear_all(inv);  
    282.     FREE_S(inv)  
    283. }  
    284. rpc_param_descriptor* rpc_invoke_bind_param(rpc_invoke_descriptor *inv, ushort id, word_t type, void *vaddr, size_t array_size, BOOL is_owner)  
    285. {  
    286.     rpc_param_descriptor* p;  
    287.     assert(id>=0 && id<inv->num_params);  
    288.     p = &inv->params_list[id];  
    289.     p->param_type = type;  
    290.     p->size_type = RPC_TYPE_SIZE(type);    
    291.     p->array_size = array_size;  
    292.     p->param_bytes = vaddr;      // may be NULL   
    293.     if (type == RPCT_STRING)  
    294.         p->param_size = array_size;  
    295.     else  
    296.         p->param_size = p->size_type * (array_size > 0? array_size : 1);  
    297.           
    298.     p->is_owner = is_owner;  
    299.     return p;  
    300. }  
    301. void rpc_param_clear(rpc_param_descriptor *p)  
    302. {  
    303.     if (p->is_owner)  
    304.         FREE_S(p->param_bytes)  
    305.       
    306.     memset(p, 0, sizeof(rpc_param_descriptor));  
    307. }  
    308. void rpc_param_free_list(rpc_param_descriptor *param_list, word_t num_params)  
    309. {  
    310.     while(num_params-->0)  
    311.         rpc_param_clear(&param_list[num_params]);  
    312.     FREE_S(param_list)  
    313. }  
    314. RPCRESULT rpc_connection_create(rpc_connection_descriptor **conn, const char *host, const char *port, long rcvtimeo, rpc_invoke_error *err)  
    315. {  
    316.     WSADATA   wsd;  
    317.     struct timeval tv_out;  
    318.     int       i;  
    319.     // 加載WinSock DLL   
    320.     if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)  
    321.         return rpc_throw_error(RPC_USER_ERROR, RPC_WINSOCK_NOTFOUND, "WSAStartup()", err);  
    322.     // 創建對象   
    323.     MALLOC_S(*conn, 1, rpc_connection_descriptor)  
    324.       
    325.     // 設置字節順序   
    326.     (*conn)->is_bigendian = _rpc_is_bigendian;  
    327.     // 設置主機名   
    328.     if (!host || host[0]==0)  
    329.         strcpy_s((*conn)->host, 128, "localhost");  
    330.     else if (strlen(host)<128)  
    331.         strcpy_s((*conn)->host, 128,  host);  
    332.     else {  
    333.         rpc_connection_free(*conn);  
    334.         return rpc_throw_error(RPC_USER_ERROR, RPC_HOSTNAME_TOOLONG, "rpc_connection_create()", err);  
    335.     }  
    336.       
    337.     // 設置端口號:   
    338.     // 必須是 gde:xxxx   
    339.     if (!port || port[0]==0 || strlen(port)<4 || strlen(port)>5) {  
    340.         rpc_connection_free(*conn);  
    341.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_PORT, "rpc_connection_create()", err);  
    342.     }  
    343.     i = 0;  
    344.     while( port[i] != 0 ){  
    345.         if ( !isdigit(port[i]) ){  
    346.             rpc_connection_free(*conn);  
    347.             return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_PORT, "rpc_connection_create()", err);         
    348.         }  
    349.         i++;  
    350.     }  
    351.     i = atoi(port);  
    352.     if (i<0x0400 || i>0xFFFF) { // port = [1024,65535]   
    353.         rpc_connection_free(*conn);  
    354.         return rpc_throw_error(RPC_USER_ERROR, RPC_PORTNUM_OUTOF_SCOPE, "rpc_connection_create()", err);  
    355.     }  
    356.     strcpy_s((*conn)->port, 6, port);  
    357.           
    358.     // 打開SOCKET   
    359.     if (RPC_SUCCESS != opensocket(&((*conn)->stream), host, i, err)){  
    360.         rpc_connection_free(*conn);  
    361.         return RPC_ERROR;  
    362.     }  
    363.     /* 
    364.      * set timeout for recv */  
    365.     if (rcvtimeo >= 0){  
    366.         tv_out.tv_sec  = rcvtimeo/1000;  
    367.         tv_out.tv_usec = (rcvtimeo%1000)*1000;  
    368.         i = setsockopt((*conn)->stream, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv_out, sizeof(tv_out));  
    369.         assert(i == 0);  
    370.     }  
    371.     (*conn)->timeout = rcvtimeo;  
    372.     return RPC_SUCCESS;  
    373. }  
    374. void rpc_connection_free(rpc_connection_descriptor *conn)  
    375. {  
    376.     if (conn){  
    377.         closesocket(conn->stream);  
    378.         WSACleanup();  
    379.         FREE_S(conn)  
    380.     }  
    381. }  
    382. void rpc_connection_set(rpc_connection_descriptor *conn, dword_t token, dword_t timeout, byte enc_hdr, byte enc_pkg)  
    383. {  
    384.     conn->token = token;  
    385.     conn->timeout = timeout;  
    386.     conn->enc_hdr = enc_hdr;  
    387.     conn->enc_pkg = enc_pkg;  
    388. }  
    389. // 計算參數字節總數   
    390. dword_t rpc_param_get_size(rpc_param_descriptor *param)  
    391. {  
    392.     return RPC_PARAM_HEADER_SIZE + (dword_t)param->param_size;  
    393. }  
    394. // 計算調用消息的字節總數   
    395. dword_t rpc_invoke_get_size(rpc_invoke_descriptor *inv)  
    396. {  
    397.     ushort   i;  
    398.     dword_t  cbTotal = RPC_INVOKE_HEADER_SIZE;  
    399.       
    400.     // 列集頭24字節:   
    401.     //   ['RCmn'(4)|用戶標識(4)|總消息字節(4)|標志(2)| 保留(2)|返回值(4)|方法序號(2)|參數數目(2)]   
    402.     // 計算列集參數字節   
    403.     for (i=0; i<inv->num_params; i++)  
    404.         cbTotal += rpc_param_get_size(&(inv->params_list[i]));  
    405.       
    406.     return cbTotal;  
    407. }  
    408. // 把當前調用的數據全部放到totalBuf中, 返回全部字節數   
    409. /*  24字節頭 + 內容 
    410.  *  ['RCmn'(4)|用戶token(4)|總消息字節(4)|標志(2)| 保留(2)|返回值(4)|方法序號(2)|參數數目(2)] 
    411.  */  
    412. int rpc_invoke_marshal(rpc_invoke_descriptor *inv, char *totalBuf, int totalSize)  
    413. {  
    414.     word_t   w;  
    415.     dword_t  dw;  
    416.     dword_t  pos;  
    417.     char     key[33];  
    418.     SET_BIT(inv->bitsFlag, RPC_BIGENDIAN_BIT, inv->bigEndian);  
    419.     SET_BIT(inv->bitsFlag, RPC_ENCHEADER_BIT, inv->encHdr==0? 0:1);  
    420.     SET_BIT(inv->bitsFlag, RPC_ENCPACKAGE_BIT, inv->encPkg==0? 0:1);  
    421.     // 列集方法頭   
    422.     totalBuf[0] = 'R';  
    423.     totalBuf[1] = 'C';  
    424.     totalBuf[2] = inv->encPkg;  
    425.     totalBuf[3] = inv->encHdr;  
    426.     pos = 4;  
    427.     dw = dword_hton(inv->invToken);  
    428.     memcpy(totalBuf+pos, &dw, 4);  
    429.     pos += 4;  
    430.     dw = dword_hton(totalSize);  
    431.     memcpy(totalBuf+pos, &dw, 4);  
    432.     pos += 4;  
    433.           
    434.     w = word_hton(inv->bitsFlag);  
    435.     memcpy(totalBuf+pos, &w, 2);  
    436.     pos += 2;  
    437.     w = 0;  
    438.     memcpy(totalBuf+pos, &w, 2);  
    439.     pos += 2;  
    440.     dw = dword_hton(inv->result);  
    441.     memcpy(totalBuf+pos, &dw, 4);  
    442.     pos += 4;  
    443.     w = word_hton(inv->ordinal);  
    444.     memcpy(totalBuf+pos, &w, 2);  
    445.     pos += 2;  
    446.     w = word_hton(inv->num_params);  
    447.     memcpy(totalBuf+pos, &w, 2);  
    448.     pos += 2;  
    449.     assert(pos==RPC_INVOKE_HEADER_SIZE);  
    450.           
    451.     // 列集每個參數   
    452.     for (w=0; w<inv->num_params; w++){  
    453.         assert((int)pos<=totalSize);  
    454.         pos += rpc_param_marshal(&inv->params_list[w], totalBuf+pos);          
    455.     }  
    456.     // 加密包數據   
    457.     if (inv->encPkg != 0){  
    458.         dword_t dw = inv->encPkg;  
    459.         srand(dw);  
    460.         MD5_hash_string(totalBuf, RPC_INVOKE_HEADER_SIZE, (dw<<24)+rand(), key);  
    461.         RC4_encrypt_string(totalBuf+RPC_INVOKE_HEADER_SIZE, totalSize-RPC_INVOKE_HEADER_SIZE, key+8, 16);  
    462.     }  
    463.     // 加密消息頭   
    464.     if (inv->encHdr != 0){  
    465.         dw = inv->encHdr;  
    466.         srand(dw);  
    467.         MD5_hash_string(totalBuf, 8, (dw<<16)+rand(), key);  
    468.         RC4_encrypt_string(totalBuf+4, RPC_INVOKE_HEADER_SIZE-4, key, 16);  
    469.     }  
    470.     return pos;   
    471. }  
    472. /**  
    473.  * 散集調用頭  
    474.  */  
    475. RPCRESULT rpc_invokehdr_unmarshal(SOCKET sClient, dword_t dwToken, char *rpcHdr, int hdrSize, rpc_invoke_descriptor *inv, rpc_invoke_error *err)  
    476. {  
    477.     /** 
    478.      * Perform a blocking recv() call 
    479.      *  ['RCmn'(4)|用戶標識(4)|總消息字節(4)|標志(2)| 保留(2)|返回值(4)|方法序號(2)|參數數目(2)] */  
    480.     assert(hdrSize == RPC_INVOKE_HEADER_SIZE);  
    481.     if (RPC_INVOKE_HEADER_SIZE != recvmsg(sClient, rpcHdr, RPC_INVOKE_HEADER_SIZE, 0))  
    482.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "RecvRpcCallHeader", err);  
    483.               
    484.     // 讀調用聲明 = "RPCn", n為0-255的密鑰種子. 0表示不加密; !=0表示RC4加密的密鑰種子   
    485.     if (rpcHdr[0]!='R'||rpcHdr[1]!='C')  
    486.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "RecvRpcCallHeader", err);  
    487.     inv->encPkg = rpcHdr[2];  
    488.     inv->encHdr = rpcHdr[3];  
    489.     if (inv->encHdr != 0){  
    490.         dword_t dw;  
    491.         char    hdr[41];  
    492.         hdr[0]=rpcHdr[0];  
    493.         hdr[1]=rpcHdr[1];  
    494.         hdr[2]=rpcHdr[2];  
    495.         hdr[3]=rpcHdr[3];  
    496.           
    497.         dw = dword_hton(dwToken);  
    498.         memcpy(&hdr[4], &dw, 4);  
    499.         dw=inv->encHdr;  
    500.         srand(dw);  
    501.         MD5_hash_string(hdr, 8, (dw<<16)+rand(), hdr+8);  
    502.         RC4_encrypt_string(rpcHdr+4, RPC_INVOKE_HEADER_SIZE-4, hdr+8, 16);  
    503.     }  
    504.       
    505.     inv->invToken = dword_ntoh(*((dword_t*)(rpcHdr+4)));         // 用戶標識    
    506.     inv->totalBytes = dword_ntoh(*((dword_t*)(rpcHdr+8)));           // 總消息字節數(也許是壓縮的)   
    507.     inv->bitsFlag = word_ntoh(*((word_t*)(rpcHdr+12)));              // 標志      
    508.     inv->bigEndian = GET_BIT(inv->bitsFlag, RPC_BIGENDIAN_BIT);       // 客戶方列集的字節次序   
    509.     inv->reserved = word_ntoh(*((word_t*)(rpcHdr+14)));              // 保留值   
    510.     inv->result = dword_ntoh(*((dword_t*)(rpcHdr+16)));              // 返回值   
    511.     inv->ordinal = word_ntoh(*((word_t*)(rpcHdr+20)));               // 方法序號   
    512.     inv->num_params = word_ntoh(*((word_t*)(rpcHdr+22)));            // 參數數目   
    513.               
    514.     return RPC_SUCCESS;  
    515. }  
    516. /* 散集數據到參數中, 數據頭總是不壓縮的. 參數數據總是先壓縮后加密的 
    517.  * 24字節頭 + 內容 
    518.  *  ['RCmn'(4)|用戶標識(4)|總消息字節(4)|標志(2)| 保留(2)|返回值(4)|方法序號(2)|參數數目(2)]  
    519.  */  
    520. RPCRESULT rpc_invoke_unmarshal(rpc_invoke_descriptor *inv,   
    521.                                char *totalBuf,   
    522.                                size_t totalSize,  
    523.                                rpc_param_descriptor **out_params,  
    524.                                word_t *num_params,  
    525.                                rpc_invoke_error *err)  
    526. {  
    527.     ushort    i;  
    528.     size_t    pos;  
    529.     rpc_param_descriptor *params_list;  
    530.     assert(totalSize >= RPC_INVOKE_HEADER_SIZE);  
    531.                   
    532.     // 讀調用聲明 = "RCmn", m,n為0-255的密鑰種子. 0表示不加密; !=0表示RC4加密的密鑰種子   
    533.     assert(totalBuf[0]=='R'&&totalBuf[1]=='C');  
    534.     // 解密包數據   
    535.     if (inv->encPkg != 0){  
    536.         char    key[33];  
    537.         dword_t dw = inv->encPkg;  
    538.         srand(dw);  
    539.         MD5_hash_string(totalBuf, RPC_INVOKE_HEADER_SIZE, (dw<<24)+rand(), key);  
    540.         RC4_encrypt_string(totalBuf+RPC_INVOKE_HEADER_SIZE, totalSize-RPC_INVOKE_HEADER_SIZE, key+8, 16);  
    541.     }  
    542.           
    543.     pos = RPC_INVOKE_HEADER_SIZE;  
    544.     // 分配參數數組   
    545.     MALLOC_S(params_list, inv->num_params, rpc_param_descriptor)  
    546.     for (i=0; i<inv->num_params; i++){  
    547.         pos += rpc_param_unmarshal(inv->bigEndian, &params_list[i], totalBuf+pos);  
    548.     }     
    549.     *out_params = params_list;  
    550.     *num_params = inv->num_params;  
    551.     assert(pos == totalSize);     
    552.     return RPC_SUCCESS;  
    553. }  
    554. RPCRESULT rpc_invoke_execute(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_descriptor *outv, rpc_invoke_error* err)  
    555. {  
    556.     inv->encHdr    = conn->enc_hdr;  
    557.     inv->encPkg    = conn->enc_pkg;     
    558.     inv->invToken  = conn->token;  
    559.     inv->bigEndian = conn->is_bigendian? 1:0;  
    560.     if (RPC_SUCCESS != rpc_invoke_send(conn, inv, err)){  
    561.         assert(0);  
    562.         return err->err_code;  
    563.     }  
    564.     if (RPC_SUCCESS != rpc_invoke_recv(conn, outv, err))  
    565.         return err->err_code;  
    566.     return RPC_SUCCESS;  
    567. }  

     

     

    整個工程的代碼隨后上傳:

     

    http://cheungmine.download.csdn.net/

     

     

    from:http://blog.csdn.net/ubuntu64fan/article/details/5660975

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全