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文件夾,內容如下:
#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 <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;
};
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<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;
}
這裏之所以輸出UNICODE字符串,是因爲在我的機器上pStr->value()會使程序崩潰,如果你的也這樣,可以找到String::value()的代碼:
return to_string(_value);
改成:
return to_utf8_string(_value);
然後就可以:
cout << pStr->value() << endl;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章