从官网下的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
如果是Linux下就:

#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;
};
hessian_proxy.cpp:
#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;
}
下面我们就可以编写测试代码了:
新建一个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;
}
这里之所以输出UNICODE字符串,是因为在我的机器上pStr->value()会使程序崩溃,如果你的也这样,可以找到String::value()的代码:
return to_string(_value);
改成:
return to_utf8_string(_value);
然后就可以:
cout << pStr->value() << endl;