從官網下的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文件夾,內容如下:
#ifndef __INTTYPES_H_
#define __INTTYPES_H_
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef int int16_t;
typedef unsigned int uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef int16_t intptr_t;
typedef uint16_t uintptr_t;
#endif
#define __INTTYPES_H_
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef int int16_t;
typedef unsigned int uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef int16_t intptr_t;
typedef uint16_t uintptr_t;
#endif
#include <sys/types.h>
#ifndef __INTTYPES_H_
#define __INTTYPES_H_
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int int16_t;
typedef unsigned short int uint16_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef int intptr_t;
typedef unsigned int uintptr_t;
#endif
然後就可以編寫我們自己的代理hessian_proxy,直接上代碼:
hessian_proxy.h:
#pragma once
#include "hessian_input.h"
#include "hessian_output.h"
#include "input_stream.h"
#include "string_input_stream.h"
#include "wrappers.h"
#include "curl.h"
using namespace std;
using namespace hessian;
using namespace hessian::wrappers;
#pragma comment(lib, "libcurl_imp.lib")
#ifdef UNICODE
#define ONE_CHAR_BYTE_NUM 2
#else
#define ONE_CHAR_BYTE_NUM 1
#endif
class hessian_proxy
{
public:
hessian_proxy(const string& url);
public:
~hessian_proxy(void);
public:
Object* call(const string& method, int argc, ... );
string get_ip() const; //返回主機地址
string get_url() const; //返回url
long get_port() const; //返回端口號
double bytes_upload(); //返回發出的總字節數
double bytes_download(); //返回收到的總字節數
string get_error_info();
static long num_calls(); //返回呼叫次數
static size_t write_data(void *buffer, size_t size, size_t nmemb, void *stream); //curl處理接受數據的回調函數
void inline set_share_handle(); //設置共享對象
//static map<string, unsigned int>& call_size_map();
private:
string _url;
CURL *_curl;
CURLcode _res;
curl_slist *_http_headers;
static CURLSH *_share_handle;
static string _http_result;
static unsigned int _num_calls;
bool _swap_OK;
bool _is_exception;
char error_buf[1024];
string _str_exception;
//static map<string, unsigned int> _call_size_map;
};
#include "hessian_input.h"
#include "hessian_output.h"
#include "input_stream.h"
#include "string_input_stream.h"
#include "wrappers.h"
#include "curl.h"
using namespace std;
using namespace hessian;
using namespace hessian::wrappers;
#pragma comment(lib, "libcurl_imp.lib")
#ifdef UNICODE
#define ONE_CHAR_BYTE_NUM 2
#else
#define ONE_CHAR_BYTE_NUM 1
#endif
class hessian_proxy
{
public:
hessian_proxy(const string& url);
public:
~hessian_proxy(void);
public:
Object* call(const string& method, int argc, ... );
string get_ip() const; //返回主機地址
string get_url() const; //返回url
long get_port() const; //返回端口號
double bytes_upload(); //返回發出的總字節數
double bytes_download(); //返回收到的總字節數
string get_error_info();
static long num_calls(); //返回呼叫次數
static size_t write_data(void *buffer, size_t size, size_t nmemb, void *stream); //curl處理接受數據的回調函數
void inline set_share_handle(); //設置共享對象
//static map<string, unsigned int>& call_size_map();
private:
string _url;
CURL *_curl;
CURLcode _res;
curl_slist *_http_headers;
static CURLSH *_share_handle;
static string _http_result;
static unsigned int _num_calls;
bool _swap_OK;
bool _is_exception;
char error_buf[1024];
string _str_exception;
//static map<string, unsigned int> _call_size_map;
};
#include "hessian_proxy.h"
unsigned int hessian_proxy::_num_calls = 0;
CURLSH* hessian_proxy::_share_handle = NULL;
string hessian_proxy:: _http_result;
hessian_proxy::hessian_proxy(const string& url)
{
_url = url;
curl_global_init(CURL_GLOBAL_DEFAULT); //初始化libcurl需要的環境
_curl = curl_easy_init(); //初始化一個 libcurl easy 句柄
if (!_curl)
{
printf("error handle\n");
return;
}
set_share_handle( );
_http_headers = NULL;
//設置http頭
_http_headers = curl_slist_append(_http_headers, "Content-Type:application/x-hessian");
curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _http_headers);
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, &write_data); //指定處理接受數據的回調函數
//char p[1024];
//curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &p);
//curl_easy_setopt(_curl, CURLOPT_TIMEOUT, 60); //設置設置傳輸時間
curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, 3); //設置連接等待時間
curl_easy_setopt(_curl, CURLOPT_ERRORBUFFER, &error_buf); //output error info
//curl_easy_setopt(_curl, CURLOPT_VERBOSE, 1); //pint debug info
}
hessian_proxy::~hessian_proxy(void)
{
if (_swap_OK) //如果curl_easy_perform成功,釋放http頭的句柄
curl_slist_free_all(_http_headers);
curl_easy_cleanup(_curl);
curl_global_cleanup();
}
size_t hessian_proxy::write_data(void *buffer, size_t size, size_t nmemb, void *stream)
{
char httpsBuffer[1024];
memset(httpsBuffer, 0, sizeof(httpsBuffer));
memcpy(httpsBuffer, buffer, nmemb);
_http_result.assign(httpsBuffer, nmemb+1);
return nmemb * size;
}
void hessian_proxy::set_share_handle()
{
if (!_share_handle)
{
_share_handle = curl_share_init();
curl_share_setopt(_share_handle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); //鎖定DNS cache
}
curl_easy_setopt(_curl, CURLOPT_SHARE, _share_handle);
curl_easy_setopt(_curl, CURLOPT_DNS_CACHE_TIMEOUT, 60); //超時時間內(60s) 每次curl_easy_perform執行時不會再啓動解析DNS的線程了,提高效率
}
Object* hessian_proxy::call(const string& method, int argc, ... )
{
Object *result = NULL;
try
{
hessian_output hout;
string mc = hout.start_call(method);
//添加參數
va_list ap;
va_start(ap, argc);
for (int i=0; i<argc; i++)
{
Object *param = va_arg(ap, Integer*);
hout.set_parameter(mc, param);
}
va_end(ap);
hout.complete_call(mc);
_num_calls++;
curl_easy_setopt(_curl, CURLOPT_URL, _url.c_str()); //設置url
curl_easy_setopt(_curl, CURLOPT_POSTFIELDS, mc.c_str()); //設置發送的數據
curl_easy_setopt(_curl, CURLOPT_POSTFIELDSIZE, mc.length()); //數據長度
memset(error_buf, 0, sizeof(error_buf));
_res = curl_easy_perform(_curl);//執行
_swap_OK = false;
_is_exception = false;
if ( _res == CURLE_OK )
{
_swap_OK = true;
auto_ptr<input_stream> sis(new string_input_stream(_http_result));
hessian_input hes_in(sis);
hes_in.start_reply();
result = hes_in.get_result();
hes_in.complete_reply();
return result;
}
}
catch (io_exception* e)
{
_is_exception = true;
if (e)
{
_str_exception.assign(e->what());
delete e;
e = NULL;
}
if (result)
{
delete result;
result = NULL;
}
}
catch (io_exception e)
{
_is_exception = true;
_str_exception.assign(e.what());
if (result)
{
result = NULL;
}
}
return NULL;
}
/*
map<string, unsigned int>& hessian_proxy::call_size_map()
{
return m_call_size_map;
}
*/
string hessian_proxy::get_ip() const
{
char *tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_PRIMARY_IP, &tmp) == CURLE_OK )
return tmp;
return NULL;
}
string hessian_proxy::get_url() const
{
char *tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_EFFECTIVE_URL, &tmp) == CURLE_OK )
return tmp;
return NULL;
}
long hessian_proxy::get_port() const
{
long tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_PRIMARY_PORT, &tmp) == CURLE_OK )
return tmp;
return -1;
}
double hessian_proxy::bytes_upload()
{
double tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_SIZE_UPLOAD, &tmp) == CURLE_OK )
return tmp;
return -1;
}
double hessian_proxy::bytes_download()
{
double tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_SIZE_DOWNLOAD, &tmp) == CURLE_OK )
return tmp;
return -1;
}
string hessian_proxy::get_error_info()
{
if (!_swap_OK)
return error_buf;
else if (_is_exception)
return _str_exception;
else
return "Complete perform!";
}
long hessian_proxy::num_calls()
{
return _num_calls;
}
unsigned int hessian_proxy::_num_calls = 0;
CURLSH* hessian_proxy::_share_handle = NULL;
string hessian_proxy:: _http_result;
hessian_proxy::hessian_proxy(const string& url)
{
_url = url;
curl_global_init(CURL_GLOBAL_DEFAULT); //初始化libcurl需要的環境
_curl = curl_easy_init(); //初始化一個 libcurl easy 句柄
if (!_curl)
{
printf("error handle\n");
return;
}
set_share_handle( );
_http_headers = NULL;
//設置http頭
_http_headers = curl_slist_append(_http_headers, "Content-Type:application/x-hessian");
curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _http_headers);
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, &write_data); //指定處理接受數據的回調函數
//char p[1024];
//curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &p);
//curl_easy_setopt(_curl, CURLOPT_TIMEOUT, 60); //設置設置傳輸時間
curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, 3); //設置連接等待時間
curl_easy_setopt(_curl, CURLOPT_ERRORBUFFER, &error_buf); //output error info
//curl_easy_setopt(_curl, CURLOPT_VERBOSE, 1); //pint debug info
}
hessian_proxy::~hessian_proxy(void)
{
if (_swap_OK) //如果curl_easy_perform成功,釋放http頭的句柄
curl_slist_free_all(_http_headers);
curl_easy_cleanup(_curl);
curl_global_cleanup();
}
size_t hessian_proxy::write_data(void *buffer, size_t size, size_t nmemb, void *stream)
{
char httpsBuffer[1024];
memset(httpsBuffer, 0, sizeof(httpsBuffer));
memcpy(httpsBuffer, buffer, nmemb);
_http_result.assign(httpsBuffer, nmemb+1);
return nmemb * size;
}
void hessian_proxy::set_share_handle()
{
if (!_share_handle)
{
_share_handle = curl_share_init();
curl_share_setopt(_share_handle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); //鎖定DNS cache
}
curl_easy_setopt(_curl, CURLOPT_SHARE, _share_handle);
curl_easy_setopt(_curl, CURLOPT_DNS_CACHE_TIMEOUT, 60); //超時時間內(60s) 每次curl_easy_perform執行時不會再啓動解析DNS的線程了,提高效率
}
Object* hessian_proxy::call(const string& method, int argc, ... )
{
Object *result = NULL;
try
{
hessian_output hout;
string mc = hout.start_call(method);
//添加參數
va_list ap;
va_start(ap, argc);
for (int i=0; i<argc; i++)
{
Object *param = va_arg(ap, Integer*);
hout.set_parameter(mc, param);
}
va_end(ap);
hout.complete_call(mc);
_num_calls++;
curl_easy_setopt(_curl, CURLOPT_URL, _url.c_str()); //設置url
curl_easy_setopt(_curl, CURLOPT_POSTFIELDS, mc.c_str()); //設置發送的數據
curl_easy_setopt(_curl, CURLOPT_POSTFIELDSIZE, mc.length()); //數據長度
memset(error_buf, 0, sizeof(error_buf));
_res = curl_easy_perform(_curl);//執行
_swap_OK = false;
_is_exception = false;
if ( _res == CURLE_OK )
{
_swap_OK = true;
auto_ptr<input_stream> sis(new string_input_stream(_http_result));
hessian_input hes_in(sis);
hes_in.start_reply();
result = hes_in.get_result();
hes_in.complete_reply();
return result;
}
}
catch (io_exception* e)
{
_is_exception = true;
if (e)
{
_str_exception.assign(e->what());
delete e;
e = NULL;
}
if (result)
{
delete result;
result = NULL;
}
}
catch (io_exception e)
{
_is_exception = true;
_str_exception.assign(e.what());
if (result)
{
result = NULL;
}
}
return NULL;
}
/*
map<string, unsigned int>& hessian_proxy::call_size_map()
{
return m_call_size_map;
}
*/
string hessian_proxy::get_ip() const
{
char *tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_PRIMARY_IP, &tmp) == CURLE_OK )
return tmp;
return NULL;
}
string hessian_proxy::get_url() const
{
char *tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_EFFECTIVE_URL, &tmp) == CURLE_OK )
return tmp;
return NULL;
}
long hessian_proxy::get_port() const
{
long tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_PRIMARY_PORT, &tmp) == CURLE_OK )
return tmp;
return -1;
}
double hessian_proxy::bytes_upload()
{
double tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_SIZE_UPLOAD, &tmp) == CURLE_OK )
return tmp;
return -1;
}
double hessian_proxy::bytes_download()
{
double tmp;
if ( curl_easy_getinfo(_curl, CURLINFO_SIZE_DOWNLOAD, &tmp) == CURLE_OK )
return tmp;
return -1;
}
string hessian_proxy::get_error_info()
{
if (!_swap_OK)
return error_buf;
else if (_is_exception)
return _str_exception;
else
return "Complete perform!";
}
long hessian_proxy::num_calls()
{
return _num_calls;
}
下面我們就可以編寫測試代碼了:
新建一個main.cpp,加入:
#include "hessian_proxy.h"
#include <iostream>
using namespace std;
int main()
{
hessian_proxy proxy("http://127.0.0.1:8080/hessian/HessianApi");
Object* result = proxy.call("hello", 0);
String* pStr = dynamic_cast<String *>(result);
wcout << pStr->wvalue() << endl;
getchar();
return 0;
}
#include <iostream>
using namespace std;
int main()
{
hessian_proxy proxy("http://127.0.0.1:8080/hessian/HessianApi");
Object* result = proxy.call("hello", 0);
String* pStr = dynamic_cast<String *>(result);
wcout << pStr->wvalue() << endl;
getchar();
return 0;
}
return to_string(_value);
改成:
return to_utf8_string(_value);
然後就可以:
cout << pStr->value() << endl;