hessiancpp编译与使用
从官网下的hessiancpp源码一直无法编译通过,后来索性放弃了自带的代理,使用另一个第三方开源库libcurl重写了一个代理,编译通过,可用且性能比较满意
1、提取hessiancpp中需要的文件
提取其中的如下文件:
exceptions.h
input_stream.h
hessian_input.h / cpp
hessian_output.h / cpp
string_input_stream.h / cpp
wrappers.h / cpp
为了方便管理,*.h放入文件夹include, *.cpp放入source
2、编译libcurl
从官网下载libcurl的源码包(最上面的Source Archives):http://curl.haxx.se/download.html
这个打开应该有2个项目,只编译libcurl,我没有遇到问题,直接编译通过
提取需要的文件:
找到include\curl,将所有的.h文件复制到上面的include文件夹
编译生成的dll和lib在 \lib\DLL-Release下libcurl_imp.lib和libcurl.dll
3、建立工程
新建一个空的控制台工程hessiancpp_test,将include、source和libcurl_imp.lib、libcurl.dll复制到工程目录
把.\include加入到附加包含目录,libcurl_imp.lib加入附加依赖项(或者源文件中加#pragma comment(lib, "libcurl_imp.lib"))
还有必须把source中的.cpp文件加入工程
编译的时候可能提示找不到inttypes.h,去google下一个或自己写一个放入include文件夹,内容如下:
1 #ifndef __INTTYPES_H_ 2 #define __INTTYPES_H_ 3 4 typedef signed char int8_t; 5 typedef unsigned char uint8_t; 6 7 typedef int int16_t; 8 typedef unsigned int uint16_t; 9 10 typedef long int32_t; 11 typedef unsigned long uint32_t; 12 13 typedef long long int64_t; 14 typedef unsigned long long uint64_t; 15 16 typedef int16_t intptr_t; 17 typedef uint16_t uintptr_t; 18 19 #endif
如果是Linux下就:
1 #include <sys/types.h> 2 3 #ifndef __INTTYPES_H_ 4 #define __INTTYPES_H_ 5 6 typedef signed char int8_t; 7 typedef unsigned char uint8_t; 8 9 typedef short int int16_t; 10 typedef unsigned short int uint16_t; 11 12 typedef long long int64_t; 13 typedef unsigned long long uint64_t; 14 15 typedef int intptr_t; 16 typedef unsigned int uintptr_t; 17 18 #endif
然后就可以编写我们自己的代理hessian_proxy,直接上代码:
hessian_proxy.h:
1 #pragma once 2 3 #include "hessian_input.h" 4 #include "hessian_output.h" 5 #include "input_stream.h" 6 #include "string_input_stream.h" 7 #include "wrappers.h" 8 #include "curl.h" 9 using namespace std; 10 using namespace hessian; 11 using namespace hessian::wrappers; 12 13 #pragma comment(lib, "libcurl_imp.lib") 14 15 #ifdef UNICODE 16 #define ONE_CHAR_BYTE_NUM 2 17 #else 18 #define ONE_CHAR_BYTE_NUM 1 19 #endif 20 21 class hessian_proxy 22 { 23 public: 24 hessian_proxy(const string& url); 25 public: 26 ~hessian_proxy(void); 27 28 public: 29 Object* call(const string& method, int argc, ... ); 30 string get_ip() const; //返回主机地址 31 string get_url() const; //返回url 32 long get_port() const; //返回端口号 33 double bytes_upload(); //返回发出的总字节数 34 double bytes_download(); //返回收到的总字节数 35 string get_error_info(); 36 static long num_calls(); //返回呼叫次数 37 static size_t write_data(void *buffer, size_t size, size_t nmemb, void *stream); //curl处理接受数据的回调函数 38 void inline set_share_handle(); //设置共享对象 39 40 //static map<string, unsigned int>& call_size_map(); 41 42 private: 43 string _url; 44 CURL *_curl; 45 CURLcode _res; 46 47 curl_slist *_http_headers; 48 49 static CURLSH *_share_handle; 50 static string _http_result; 51 static unsigned int _num_calls; 52 53 bool _swap_OK; 54 bool _is_exception; 55 char error_buf[1024]; 56 string _str_exception; 57 58 //static map<string, unsigned int> _call_size_map; 59 };
hessian_proxy.cpp:
1 #include "hessian_proxy.h" 2 3 unsigned int hessian_proxy::_num_calls = 0; 4 CURLSH* hessian_proxy::_share_handle = NULL; 5 string hessian_proxy:: _http_result; 6 7 hessian_proxy::hessian_proxy(const string& url) 8 { 9 _url = url; 10 curl_global_init(CURL_GLOBAL_DEFAULT); //初始化libcurl需要的环境 11 _curl = curl_easy_init(); //初始化一个 libcurl easy 句柄 12 if (!_curl) 13 { 14 printf("error handle\n"); 15 return; 16 } 17 set_share_handle( ); 18 _http_headers = NULL; 19 //设置http头 20 _http_headers = curl_slist_append(_http_headers, "Content-Type:application/x-hessian"); 21 curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _http_headers); 22 curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, &write_data); //指定处理接受数据的回调函数 23 //char p[1024]; 24 //curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &p); 25 //curl_easy_setopt(_curl, CURLOPT_TIMEOUT, 60); //设置设置传输时间 26 curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, 3); //设置连接等待时间 27 curl_easy_setopt(_curl, CURLOPT_ERRORBUFFER, &error_buf); //output error info 28 29 //curl_easy_setopt(_curl, CURLOPT_VERBOSE, 1); //pint debug info 30 31 } 32 33 hessian_proxy::~hessian_proxy(void) 34 { 35 if (_swap_OK) //如果curl_easy_perform成功,释放http头的句柄 36 curl_slist_free_all(_http_headers); 37 curl_easy_cleanup(_curl); 38 curl_global_cleanup(); 39 } 40 41 size_t hessian_proxy::write_data(void *buffer, size_t size, size_t nmemb, void *stream) 42 { 43 char httpsBuffer[1024]; 44 memset(httpsBuffer, 0, sizeof(httpsBuffer)); 45 memcpy(httpsBuffer, buffer, nmemb); 46 47 _http_result.assign(httpsBuffer, nmemb+1); 48 49 return nmemb * size; 50 } 51 52 void hessian_proxy::set_share_handle() 53 { 54 if (!_share_handle) 55 { 56 _share_handle = curl_share_init(); 57 curl_share_setopt(_share_handle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); //锁定DNS cache 58 } 59 curl_easy_setopt(_curl, CURLOPT_SHARE, _share_handle); 60 curl_easy_setopt(_curl, CURLOPT_DNS_CACHE_TIMEOUT, 60); //超时时间内(60s) 每次curl_easy_perform执行时不会再启动解析DNS的线程了,提高效率 61 } 62 63 Object* hessian_proxy::call(const string& method, int argc, ... ) 64 { 65 Object *result = NULL; 66 try 67 { 68 hessian_output hout; 69 string mc = hout.start_call(method); 70 71 //添加参数 72 va_list ap; 73 va_start(ap, argc); 74 for (int i=0; i<argc; i++) 75 { 76 Object *param = va_arg(ap, Integer*); 77 hout.set_parameter(mc, param); 78 } 79 va_end(ap); 80 hout.complete_call(mc); 81 82 _num_calls++; 83 84 curl_easy_setopt(_curl, CURLOPT_URL, _url.c_str()); //设置url 85 curl_easy_setopt(_curl, CURLOPT_POSTFIELDS, mc.c_str()); //设置发送的数据 86 curl_easy_setopt(_curl, CURLOPT_POSTFIELDSIZE, mc.length()); //数据长度 87 memset(error_buf, 0, sizeof(error_buf)); 88 89 _res = curl_easy_perform(_curl);//执行 90 _swap_OK = false; 91 _is_exception = false; 92 if ( _res == CURLE_OK ) 93 { 94 _swap_OK = true; 95 auto_ptr<input_stream> sis(new string_input_stream(_http_result)); 96 hessian_input hes_in(sis); 97 hes_in.start_reply(); 98 99 result = hes_in.get_result(); 100 hes_in.complete_reply(); 101 102 return result; 103 } 104 105 } 106 catch (io_exception* e) 107 { 108 _is_exception = true; 109 if (e) 110 { 111 _str_exception.assign(e->what()); 112 delete e; 113 e = NULL; 114 } 115 if (result) 116 { 117 delete result; 118 result = NULL; 119 } 120 } 121 catch (io_exception e) 122 { 123 _is_exception = true; 124 _str_exception.assign(e.what()); 125 if (result) 126 { 127 result = NULL; 128 } 129 } 130 131 return NULL; 132 } 133 /* 134 map<string, unsigned int>& hessian_proxy::call_size_map() 135 { 136 return m_call_size_map; 137 } 138 */ 139 140 string hessian_proxy::get_ip() const 141 { 142 char *tmp; 143 if ( curl_easy_getinfo(_curl, CURLINFO_PRIMARY_IP, &tmp) == CURLE_OK ) 144 return tmp; 145 return NULL; 146 } 147 148 149 string hessian_proxy::get_url() const 150 { 151 char *tmp; 152 if ( curl_easy_getinfo(_curl, CURLINFO_EFFECTIVE_URL, &tmp) == CURLE_OK ) 153 return tmp; 154 return NULL; 155 } 156 157 long hessian_proxy::get_port() const 158 { 159 long tmp; 160 if ( curl_easy_getinfo(_curl, CURLINFO_PRIMARY_PORT, &tmp) == CURLE_OK ) 161 return tmp; 162 return -1; 163 } 164 165 double hessian_proxy::bytes_upload() 166 { 167 double tmp; 168 if ( curl_easy_getinfo(_curl, CURLINFO_SIZE_UPLOAD, &tmp) == CURLE_OK ) 169 return tmp; 170 return -1; 171 } 172 173 double hessian_proxy::bytes_download() 174 { 175 double tmp; 176 if ( curl_easy_getinfo(_curl, CURLINFO_SIZE_DOWNLOAD, &tmp) == CURLE_OK ) 177 return tmp; 178 return -1; 179 } 180 181 string hessian_proxy::get_error_info() 182 { 183 if (!_swap_OK) 184 return error_buf; 185 else if (_is_exception) 186 return _str_exception; 187 else 188 return "Complete perform!"; 189 } 190 191 long hessian_proxy::num_calls() 192 { 193 return _num_calls; 194 }
下面我们就可以编写测试代码了:
新建一个main.cpp,加入:
1 #include "hessian_proxy.h" 2 #include <iostream> 3 using namespace std; 4 5 int main() 6 { 7 hessian_proxy proxy("http://127.0.0.1:8080/hessian/HessianApi"); 8 9 Object* result = proxy.call("hello", 0); 10 String* pStr = dynamic_cast<String *>(result); 11 wcout << pStr->wvalue() << endl; 12 13 getchar(); 14 return 0; 15 }
这里之所以输出UNICODE字符串,是因为在我的机器上pStr->value()会使程序崩溃,如果你的也这样,可以找到String::value()的代码:
return to_string(_value);
改成:
return to_utf8_string(_value);
然后就可以:
cout << pStr->value() << endl;
本文最早写在51cto上:http://mayacong.blog.51cto.com/3724695/723842