从官网下的hessiancpp源码一直无法编译通过,后来索性放弃了自带的代理,使用另一个第三方开源库libcurl重写了一个代理,编译通过,可用且性能比较满意
1、提取hessiancpp中需要的文件
去官网下载源码包: http://sourceforge.net/projects/hessiancpp/files/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
#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& 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 _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
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
};
#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 {
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 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& 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
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
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
{
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
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(result);
wcout << pStr->wvalue() << endl;
getchar();
return 0;
}
#include
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
wcout << pStr->wvalue() << endl;
getchar();
return 0;
}
return to_string(_value);
改成:
return to_utf8_string(_value);
然后就可以:
cout << pStr->value() << endl;