c++缺少web开发的框架,web框架分为异步和同步,异步的业务逻辑控制需要较强功底,同步代码实现起来容易,利于阅读理解

1.gsoap是c++写的webservice库,webservice应用层也是用http进行传输的,gsoap提供了httpget和httppost的插件,本文对这两个插件进行改造,可以支持restful风格的接口。下面是的代码需要在c++11支持的编译器下运行,rest包装的内容用json传递

2.利于gsoap的soapcpp2.exe工具生成env文件

命令

mkdir env

soapcpp2.exe -penv -denv env.h

3.拷贝源码目录下的stdsoap2.h和stdsoap2.cpp,和http插件包含进你的工程

4.server文件

  1. #ifndef SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__
  2. #define SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__
  3.  
  4. #include <string>
  5. #include <map>
  6. #include <list>
  7. #include <queue>
  8. #include <mutex>
  9. #include <condition_variable>
  10. #include <thread>
  11.  
  12. using namespace std;
  13. #include "stdsoap2.h"
  14. #include "RestServicePlugin.h"
  15. using namespace Http;
  16.  
  17. class CSoapWebServer
  18. {
  19. public:
  20. CSoapWebServer();
  21. ~CSoapWebServer();
  22.  
  23. static const int AcceptTimeout = ;//>单位s
  24. static const int RecvTimeout = ;//>单位s
  25. static const int SendTimeout = ;//>单位s
  26. static const int MaxThreadCount = ;
  27. static const unsigned int WaitTimeout = ; //>单位s
  28. void SetURI(const char* URI,RequestProcessFunc fun, void * user);
  29. void SetURI(const char* URI, RequestProcessFunction & fun);
  30. void ResetURI(const char* URI);
  31. void ClearURI();
  32.  
  33. bool StartService(const char* ip,unsigned int port);
  34. void StopService();
  35.  
  36. protected:
  37. struct THREAD_INFO
  38. {
  39. struct soap* soap_listen;
  40. struct soap* soap_client;
  41. CSoapWebServer* pThis;
  42. };
  43. bool StartThread();
  44. void CloseThread();
  45.  
  46. void ServiceListenThread();
  47. void ServiceServeThread(THREAD_INFO*pParam);
  48. void Listen();
  49. void ExecuteServe(THREAD_INFO* info);
  50. int SoapServ(struct soap* soap);
  51.  
  52. int BeginServe(struct soap* soap);
  53. int EndServe(struct soap* soap);
  54.  
  55. struct soap* PopSoap(void);
  56. void PushSoap(struct soap* soap);
  57. void FreeSoapAll(void);
  58. private:
  59.  
  60. CRestServicePlugin m_service;
  61. struct soap* m_pSoap;
  62. volatile bool m_bExit;
  63. std::thread *m_ListenThread; //>接收线程句柄
  64. std::thread *m_ServeThread[MaxThreadCount]; //>服务执行线程
  65. struct CLIENT_INFO
  66. {
  67. SOAP_SOCKET socket;
  68. unsigned long ip;
  69. unsigned int port;
  70. };
  71. std::queue<CLIENT_INFO> m_acceptClientList;
  72. std::queue<struct soap*> m_soapList;
  73. std::mutex m_listMt;
  74. std::condition_variable m_cvClient;
  75. unsigned int m_iClientCount;
  76. };
  77.  
  78. #endif // SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__
  1. 5.server.cpp文件
  1. #include "SoapWebServer.h"
  2. //#include "soap.nsmap"
  3.  
  4. SOAP_NMAC struct Namespace namespaces[] = {
  5. {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope", NULL},
  6. {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding", NULL},
  7. {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
  8. {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
  9. {NULL, NULL, NULL, NULL}
  10. };
  11.  
  12. int TestAPI(Request& request)
  13. {
  14. char* body = NULL;
  15. size_t body_len = request.GetBody(&body);
  16.  
  17. Response res(request);
  18. res.SetContentType("text/json");
  19. res.Send("{\"name\":\"bobo\",\"age\": 50}");
  20.  
  21. return SOAP_OK;
  22. }
  23.  
  24. CSoapWebServer::CSoapWebServer():
  25. m_pSoap(NULL),
  26. m_bExit(false),
  27. m_ListenThread(nullptr),
  28. m_iClientCount()
  29. {
  30. for (int i = ; i < MaxThreadCount; ++i)
  31. {
  32. m_ServeThread[i] = nullptr;
  33. }
  34. }
  35.  
  36. CSoapWebServer::~CSoapWebServer()
  37. {
  38.  
  39. }
  40. void CSoapWebServer::ClearURI()
  41. {
  42. m_service.ClearURI();
  43. }
  44.  
  45. void CSoapWebServer::ResetURI( const char* URI )
  46. {
  47. if (URI)
  48. {
  49. m_service.UnRegisteURI(URI);
  50. }
  51. }
  52.  
  53. void CSoapWebServer::SetURI( const char* URI,RequestProcessFunc fun, void * user)
  54. {
  55. if (!URI || !fun)
  56. {
  57. return;
  58. }
  59.  
  60. m_service.RegisteURI(URI,fun, user);
  61. }
  62.  
  63. void CSoapWebServer::SetURI(const char* URI, RequestProcessFunction & fun)
  64. {
  65. if (!URI || !fun)
  66. {
  67. return;
  68. }
  69.  
  70. m_service.RegisteURI(URI,fun);
  71. }
  72.  
  73. bool CSoapWebServer::StartService(const char* ip,unsigned int port)
  74. {
  75. //StopService();
  76. m_bExit = false;
  77. do
  78. {
  79. m_pSoap = soap_new();
  80. if (NULL == m_pSoap)
  81. {
  82. break;
  83. }
  84.  
  85. soap_init1(m_pSoap, SOAP_C_UTFSTRING);
  86. m_pSoap->bind_flags = SO_REUSEADDR;
  87. m_pSoap->send_timeout = SendTimeout;
  88. m_pSoap->recv_timeout = RecvTimeout;
  89. m_pSoap->accept_timeout = AcceptTimeout;
  90. m_pSoap->imode = SOAP_C_UTFSTRING;
  91.  
  92. m_pSoap->namespaces = namespaces;
  93. soap_set_local_namespaces(m_pSoap);
  94.  
  95. m_service.Hook(m_pSoap);
  96. {
  97. FreeSoapFunction fun((FreeSoapFunction)std::tr1::bind(
  98. &CSoapWebServer::PushSoap, this, std::tr1::placeholders::_1));
  99. m_service.RegisterFreeSoap(fun);
  100. }
  101.  
  102. SOAP_SOCKET serverSocket = soap_bind(m_pSoap,ip,port,);
  103. if (serverSocket == SOAP_INVALID_SOCKET)
  104. {
  105. printf("err soap_bind, %s:%u\n", ip, port);
  106. break;
  107. }
  108. printf("soap bind %s:%u\n", ip, port);
  109.  
  110. if (!StartThread())
  111. {
  112. printf("err StartThread\n");
  113. break;
  114. }
  115. printf("start success\n");
  116. return true;
  117. } while (false);
  118. printf("err start failed\n");
  119. StopService();
  120. return false;
  121. }
  122. void CSoapWebServer::StopService()
  123. {
  124. m_bExit = true;
  125. CloseThread();
  126. m_iClientCount = ;
  127.  
  128. m_service.ClearURI();
  129. FreeSoapAll();
  130. if (NULL != m_pSoap)
  131. {
  132. soap_destroy(m_pSoap);
  133. soap_end(m_pSoap);
  134. soap_done(m_pSoap);
  135. soap_free(m_pSoap);
  136. m_pSoap = NULL;
  137. }
  138. }
  139. bool CSoapWebServer::StartThread()
  140. {
  141. //>开启service接受执行线程
  142. m_ListenThread = new std::thread(
  143. &CSoapWebServer::ServiceListenThread,this);
  144.  
  145. int iThreadCount = ;
  146. if( iThreadCount > MaxThreadCount)
  147. {
  148. iThreadCount = MaxThreadCount;
  149. }
  150. else if(iThreadCount == )
  151. {
  152. iThreadCount = ;
  153. }
  154.  
  155. for (int i = ; i < iThreadCount; ++i)
  156. {
  157. soap* pSoap = soap_copy(m_pSoap);
  158. THREAD_INFO* info = new(std::nothrow)THREAD_INFO;
  159. if (info == NULL)
  160. {
  161. return false;
  162. }
  163. info->soap_listen = m_pSoap;
  164. info->soap_client = pSoap;
  165. info->pThis = this;
  166. m_ServeThread[i] = new std::thread(
  167. &CSoapWebServer::ServiceServeThread, this, info);
  168. }
  169. return true;
  170. }
  171.  
  172. void CSoapWebServer::CloseThread()
  173. {
  174. m_cvClient.notify_all();
  175. if (m_ListenThread)
  176. {
  177. m_ListenThread->join();
  178. delete m_ListenThread;
  179. m_ListenThread = nullptr;
  180. }
  181.  
  182. for (int i = ; i < MaxThreadCount; i++)
  183. {
  184. if(m_ServeThread[i])
  185. {
  186. m_ServeThread[i]->join();
  187. delete m_ServeThread[i];
  188. m_ServeThread[i] = nullptr;
  189. }
  190. }
  191. }
  192. void CSoapWebServer::ServiceListenThread()
  193. {
  194. Listen();
  195. return ;
  196. }
  197. void CSoapWebServer::Listen()
  198. {
  199. if (NULL == m_pSoap)
  200. {
  201. return ;
  202. }
  203. CLIENT_INFO clientInfo;
  204. while (!m_bExit)
  205. {
  206. clientInfo.socket = soap_accept(m_pSoap);
  207. if (clientInfo.socket != SOAP_INVALID_SOCKET )
  208. {
  209. std::unique_lock<std::mutex> guard(m_listMt);
  210. clientInfo.ip = m_pSoap->ip;
  211. clientInfo.port = m_pSoap->port;
  212. m_acceptClientList.push(clientInfo);
  213. ++m_iClientCount;
  214. m_cvClient.notify_one();
  215. }
  216. }
  217. }
  218.  
  219. void CSoapWebServer::ServiceServeThread(THREAD_INFO* pParam )
  220. {
  221. if (NULL == pParam)
  222. {
  223. return ;
  224. }
  225. THREAD_INFO* info = (THREAD_INFO*)pParam;
  226. CSoapWebServer *pThis = info->pThis;
  227.  
  228. if(NULL == pThis)
  229. {
  230. return ;
  231. }
  232. ExecuteServe(info);
  233.  
  234. delete info;
  235.  
  236. return ;
  237. }
  238. void CSoapWebServer::ExecuteServe(THREAD_INFO* info )
  239. {
  240. const int iTempSockCount = ;
  241. CLIENT_INFO tempClientArr[iTempSockCount] = {};
  242. int end_pos = ;
  243. struct soap* soap = NULL;
  244.  
  245. soap = info->soap_client;
  246. int ret = SOAP_OK;
  247.  
  248. while (!m_bExit)
  249. {
  250. {
  251. std::unique_lock<std::mutex> guard(m_listMt);
  252. if (m_acceptClientList.empty())
  253. {
  254. m_cvClient.wait(guard);
  255. }
  256. for (end_pos=;
  257. end_pos<iTempSockCount && !m_acceptClientList.empty();
  258. ++end_pos )
  259. {
  260. tempClientArr[end_pos] = m_acceptClientList.front();
  261. m_acceptClientList.pop();
  262. --m_iClientCount;
  263. }
  264. }
  265.  
  266. for (int i = ; i < end_pos; ++i)
  267. {
  268. soap->socket = tempClientArr[i].socket;
  269. soap->ip = tempClientArr[i].ip;
  270. soap->port = tempClientArr[i].port;
  271. if(!soap_valid_socket(soap->socket))
  272. {
  273. continue;
  274. }
  275.  
  276. if ((ret=BeginServe(soap)) != SOAP_OK)
  277. {
  278. //printf("serve error.code:%d msg:%s\n", soap->error,*(soap_faultstring(soap)));
  279. }
  280.  
  281. if (ret == SOAP_STOP/*(int)soap->user == RESPONSE_MODE_ASYN*/)
  282. {//异步
  283. //获取一个soap
  284. soap = PopSoap();
  285. if (soap == NULL)
  286. {//缓存没有,拷贝一个
  287. soap = soap_copy(info->soap_listen);
  288. }
  289. }
  290. else
  291. {
  292. EndServe(soap);
  293. }
  294.  
  295. soap_destroy(soap);
  296. soap_end(soap);
  297. }
  298. }
  299.  
  300. //回收
  301. PushSoap(soap);
  302. }
  303.  
  304. int CSoapWebServer::SoapServ( struct soap* soap )
  305. {
  306. #ifndef WITH_FASTCGI
  307. unsigned int k = soap->max_keep_alive;
  308. #endif
  309. do
  310. {
  311. #ifndef WITH_FASTCGI
  312. if (soap->max_keep_alive > && !--k)
  313. {
  314. soap->keep_alive = ;
  315. }
  316. #endif
  317. if (soap_begin_serve(soap))
  318. {
  319. if (soap->error >= SOAP_STOP)
  320. {
  321. continue;
  322. }
  323. return soap->error;
  324. }
  325.  
  326. #ifdef WITH_FASTCGI
  327. soap_destroy(soap);
  328. soap_end(soap);
  329. } while ();
  330. #else
  331. } while (soap->keep_alive);
  332. #endif
  333. return SOAP_OK;
  334. }
  335.  
  336. int CSoapWebServer::BeginServe(struct soap* soap)
  337. {
  338. void * user = soap->user;
  339. long ret = RESPONSE_MODE_SYN;
  340.  
  341. soap_begin(soap);
  342. if (soap_begin_recv(soap)
  343. || soap_envelope_begin_in(soap)
  344. || soap_recv_header(soap)
  345. || soap_body_begin_in(soap))
  346. { if (soap->error < SOAP_STOP)
  347. {
  348. #ifdef WITH_FASTCGI
  349. (void)soap_send_fault(soap);
  350. #else
  351. return soap_send_fault(soap);
  352. #endif
  353. }
  354. }
  355.  
  356. ret = (long)soap->user;
  357. soap->user = user;
  358.  
  359. return (ret==RESPONSE_MODE_ASYN) ? SOAP_STOP: SOAP_OK;
  360. }
  361.  
  362. int CSoapWebServer::EndServe(struct soap* soap)
  363. {
  364. return soap_closesock(soap);
  365. }
  366.  
  367. struct soap* CSoapWebServer::PopSoap(void)
  368. {
  369. struct soap * soap = NULL;
  370. std::unique_lock<std::mutex> guard(m_listMt);
  371. if (m_soapList.empty())
  372. {
  373. return NULL;
  374. }
  375. soap = m_soapList.front();
  376. m_soapList.pop();
  377.  
  378. return soap;
  379. }
  380.  
  381. void CSoapWebServer::PushSoap(struct soap* soap)
  382. {
  383. if (soap == NULL)
  384. {
  385. return ;
  386. }
  387.  
  388. std::unique_lock<std::mutex> guard(m_listMt);
  389. m_soapList.push(soap);
  390. }
  391.  
  392. void CSoapWebServer::FreeSoapAll(void)
  393. {
  394. std::queue<struct soap*> lsoap;
  395. {
  396. std::unique_lock<std::mutex> guard(m_listMt);
  397. lsoap = m_soapList;
  398. while (!m_soapList.empty())
  399. {
  400. m_soapList.pop();
  401. }
  402. }
  403.  
  404. struct soap * soap;
  405. while (!lsoap.empty())
  406. {
  407. soap = lsoap.front();
  408.  
  409. soap_destroy(soap);
  410. soap_end(soap);
  411.  
  412. soap_done(soap);
  413. soap_free(soap);
  414.  
  415. lsoap.pop();
  416. }
  417. }

6.插件头文件

  1. #ifndef RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__
  2. #define RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__
  3.  
  4. #include <string>
  5. #include <map>
  6. #include <mutex>
  7.  
  8. #if (defined _WIN32 || defined _WIN64)
  9. # include <memory> //shared_ptr
  10. # include <functional>
  11. #elif defined(__linux__)
  12. # include <tr1/memory>
  13. # include <tr1/functional>
  14. #endif
  15.  
  16. #include "stdsoap2.h"
  17. #include "httpget.h"
  18. #include "httppost.h"
  19.  
  20. namespace Http
  21. {
  22. class CRestServicePlugin;
  23. class Request;
  24.  
  25. typedef int (*RequestProcessFunc)(Request& request, void* user);
  26. typedef std::tr1::function<int(Request& request)> RequestProcessFunction;
  27. typedef std::tr1::function<void(struct soap*)> FreeSoapFunction;
  28.  
  29. enum HTTP_STATUS
  30. {
  31. HTTP_STATUS_OK = ,
  32. HTTP_STATUS_BAD_REQUEST = , // invalid syntax
  33. HTTP_STATUS_DENIED = , // access denied
  34. HTTP_STATUS_PAYMENT_REQ = , // payment required
  35. HTTP_STATUS_FORBIDDEN = , // request forbidden
  36. HTTP_STATUS_NOT_FOUND = , // object not found
  37. HTTP_STATUS_BAD_METHOD = , // method is not allowed
  38. HTTP_STATUS_NONE_ACCEPTABLE = , // no response acceptable to client found
  39. HTTP_STATUS_PROXY_AUTH_REQ = , // proxy authentication required
  40. HTTP_STATUS_REQUEST_TIMEOUT = , // server timed out waiting for request
  41. HTTP_STATUS_CONFLICT = , // user should resubmit with more info
  42. HTTP_STATUS_GONE = , // the resource is no longer available
  43. HTTP_STATUS_LENGTH_REQUIRED = , // the server refused to accept request w/o a length
  44. HTTP_STATUS_PRECOND_FAILED = , // precondition given in request failed
  45. HTTP_STATUS_REQUEST_TOO_LARGE = , // request entity was too large
  46. HTTP_STATUS_URI_TOO_LONG = , // request URI too long
  47. HTTP_STATUS_UNSUPPORTED_MEDIA = , // unsupported media type
  48. HTTP_STATUS_RETRY_WITH = , // retry after doing the appropriate action.
  49.  
  50. HTTP_STATUS_SERVER_ERROR = ,// internal server error
  51. HTTP_STATUS_NOT_SUPPORTED = , // required not supported
  52. HTTP_STATUS_BAD_GATEWAY = , // error response received from gateway
  53. HTTP_STATUS_SERVICE_UNAVAIL = , // temporarily overloaded
  54. HTTP_STATUS_GATEWAY_TIMEOUT = , // timed out waiting for gateway
  55. HTTP_STATUS_VERSION_NOT_SUP = // HTTP version not supported
  56. };
  57.  
  58. enum HTTP_METHOD
  59. {
  60. HTTP_GET = ,
  61. HTTP_POST =
  62. };
  63. enum HTTP_RES_TYPE
  64. {
  65. HTTP_HTML = ,
  66. HTTP_FILE =
  67. };
  68. typedef struct rest_str_s
  69. {
  70. size_t len; //字符串长度
  71. char* ptr; //字符串首地址
  72. }rest_str_t;
  73.  
  74. typedef struct rest_query_s
  75. {
  76. const char* key;
  77. const char* value;
  78. }rest_query_t;
  79.  
  80. static const size_t QUERY_MAX_SIZE = ; //最多参数个数
  81.  
  82. class Request
  83. {
  84. friend class CRestServicePlugin;
  85. friend class Response;
  86. public:
  87. Request()
  88. {
  89. soap = NULL;
  90. }
  91.  
  92. /** @fn Query
  93. * @brief 获取url中的请求参数
  94. * @param key:
  95. * @return 返回查询到的值
  96. */
  97. const char* Query( const char* key);
  98.  
  99. /** @fn GetBody
  100. * @brief 获取请求体
  101. * @param
  102. * @return 请求内容字节数,0为空
  103. */
  104. size_t GetBody(char** body);
  105.  
  106. HTTP_METHOD GetMethod(void){ return method;}
  107.  
  108. protected:
  109. /** @fn GetURI
  110. * @brief 获取请求的url
  111. * @param
  112. * @return
  113. */
  114. const char* GetURI();
  115.  
  116. int ReponseWithEnd(int code);
  117. /************************************
  118. >@ Method: ParseRequest
  119. >@ FullName: Http::Request::ParseRequest
  120. >@ Brief: 解析请求参数
  121. >@ Access: public
  122. >@ Returns: bool
  123. >@ Qualifier:
  124. ************************************/
  125. bool ParseRequest();
  126.  
  127. rest_query_t* GetQuery(void){return _query;}
  128.  
  129. private:
  130. rest_query_t _query[QUERY_MAX_SIZE];//请求参数
  131. HTTP_METHOD method;
  132. struct soap* soap;
  133. CRestServicePlugin * _plugin;
  134. };
  135.  
  136. #define RESPONSE_MODE_SYN 0 //同步
  137. #define RESPONSE_MODE_ASYN 1 //异步
  138.  
  139. class Response
  140. {
  141. public:
  142. Response(Request& req, int mod=RESPONSE_MODE_SYN);
  143. Response();
  144. ~Response();
  145.  
  146. /** @fn SetContentType
  147. * @brief 设置响应内容,默认为空,例如"text/json"
  148. * @param
  149. * @return
  150. */
  151. void SetContentType(const char* conttype);
  152.  
  153. /** @fn Send
  154. * @brief 发送响应数据,可以调用多次发送
  155. * @param
  156. * @return 0-发送成功
  157. */
  158. int Send(const char* data);
  159. int Send(const char* data, std::size_t len);
  160.  
  161. /** @fn BeginResponse
  162. * @brief 开始响应
  163. * @param mod:响应模式,RESPONSE_MODE_SYN-同步,RESPONSE_MODE_ASYN-异步
  164. * @return
  165. */
  166. int BeginResponse(Request& req, int mod=RESPONSE_MODE_SYN);
  167. int EndResponse(void);
  168.  
  169. protected:
  170.  
  171. private:
  172. struct soap * _soap;
  173. int _mod;
  174. CRestServicePlugin *_plugin;
  175. };
  176.  
  177. class CRestServicePlugin
  178. {
  179. friend class Response;
  180. public:
  181. CRestServicePlugin(void);
  182. ~CRestServicePlugin(void);
  183.  
  184. static int http_get_handler(struct soap*);
  185. static int http_post_text_handler(struct soap *soap);
  186. public:
  187. bool Hook(struct soap* soap);
  188. void RegisteURI(const char* URI,RequestProcessFunc fun, void* user);
  189. void RegisteURI(const char* URI, RequestProcessFunction & fun);
  190. void UnRegisteURI(const char* URI);
  191. void ClearURI();
  192.  
  193. void RegisterFreeSoap(FreeSoapFunction & fun);
  194. protected:
  195. int Process(struct soap* soap,HTTP_METHOD method);
  196. private:
  197. std::mutex m_dataMt;
  198. //uri的处理函数映射表
  199. std::map<std::size_t,RequestProcessFunction> m_uriFunMap;
  200. FreeSoapFunction _funFreeSoap;
  201. };
  202. }
  203.  
  204. #endif // RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__
  1. 7.插件cpp文件
  1. #include "RestServicePlugin.h"
  2. #include "httpget.h"
  3.  
  4. namespace Http
  5. {
  6. static const char* json_type = "application/json";
  7. static const char* http_unknow = "HTTP/1.1 -1 UNKNOW\r\nConnection: close\r\n\r\n";
  8. static const char* http_400 = "HTTP/1.1 400 BAD REQUEST\r\nConnection: close\r\n\r\n";
  9. static const char* http_404 = "HTTP/1.1 404 NOT FOUND\r\nConnection: close\r\n\r\n";
  10. static const char* http_500 = "HTTP/1.1 500 SERVER ERROR\r\nConnection: close\r\n\r\n";
  11.  
  12. //FNV hash copy from gcc
  13. // Dummy generic implementation (for sizeof(size_t) != 4, 8).
  14. template<std::size_t = sizeof(std::size_t)>
  15. struct Fnv_hash
  16. {
  17. static std::size_t
  18. hash(const char* first, std::size_t length)
  19. {
  20. std::size_t result = ;
  21. for (; length > ; --length)
  22. result = (result * ) + *first++;
  23. return result;
  24. }
  25. };
  26.  
  27. template<>
  28. struct Fnv_hash<>
  29. {
  30. static std::size_t
  31. hash(const char* first, std::size_t length)
  32. {
  33. std::size_t result = static_cast<std::size_t>(2166136261UL);
  34. for (; length > ; --length)
  35. {
  36. result ^= (std::size_t)*first++;
  37. result *= 16777619UL;
  38. }
  39. return result;
  40. }
  41. };
  42.  
  43. template<>
  44. struct Fnv_hash<>
  45. {
  46. static std::size_t
  47. hash(const char* first, std::size_t length)
  48. {
  49. std::size_t result = static_cast<std::size_t>(14695981039346656037ULL);
  50. for (; length > ; --length)
  51. {
  52. result ^= (std::size_t)*first++;
  53. result *= 1099511628211ULL;
  54. }
  55. return result;
  56. }
  57. };
  58.  
  59. http_post_handlers handlers[] =
  60. {
  61. { "POST", Http::CRestServicePlugin::http_post_text_handler },
  62. { NULL }
  63. };
  64.  
  65. //////////////////////////////////////////////////////////////////////////
  66. //CRestServicePlugin
  67. CRestServicePlugin::CRestServicePlugin(void)
  68.  
  69. {
  70. }
  71.  
  72. CRestServicePlugin::~CRestServicePlugin(void)
  73. {
  74. }
  75.  
  76. bool CRestServicePlugin::Hook( struct soap* soap )
  77. {
  78. if (NULL == soap)
  79. {
  80. return false;
  81. }
  82. soap->user = (void*)this;
  83. soap_register_plugin_arg(soap, http_get, (void*)http_get_handler);
  84. soap_register_plugin_arg(soap,http_post,(void*)handlers);
  85. return true;
  86. }
  87.  
  88. void CRestServicePlugin::RegisteURI( const char* URI,RequestProcessFunc fun , void* user)
  89. {
  90. std::tr1::function<int(Request& request)> funl;
  91. funl = std::tr1::bind(fun, std::tr1::placeholders::_1, user);
  92.  
  93. RegisteURI(URI, funl);
  94. }
  95.  
  96. void CRestServicePlugin::RegisteURI(const char* URI, RequestProcessFunction & fun)
  97. {
  98. size_t hash_uri = Fnv_hash<>::hash(URI, strlen(URI));
  99.  
  100. std::lock_guard<std::mutex> guard(m_dataMt);
  101. std::map<size_t, RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
  102. if (iter != m_uriFunMap.end())
  103. {
  104. iter->second = fun;
  105. }
  106. else
  107. {
  108. m_uriFunMap.insert(std::map<size_t,RequestProcessFunction>::value_type(hash_uri,fun));
  109. }
  110. }
  111.  
  112. void CRestServicePlugin::RegisterFreeSoap(FreeSoapFunction & fun)
  113. {
  114. _funFreeSoap = fun;
  115. }
  116.  
  117. void CRestServicePlugin::UnRegisteURI( const char* URI )
  118. {
  119. size_t hash_uri = Fnv_hash<>::hash(URI, strlen(URI));
  120.  
  121. std::lock_guard<std::mutex> guard(m_dataMt);
  122. std::map<size_t,RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
  123. if (iter != m_uriFunMap.end())
  124. {
  125. m_uriFunMap.erase(iter);
  126. }
  127. }
  128.  
  129. void CRestServicePlugin::ClearURI()
  130. {
  131. std::lock_guard<std::mutex> guard(m_dataMt);
  132. m_uriFunMap.clear();
  133. _funFreeSoap = NULL;
  134. }
  135.  
  136. int CRestServicePlugin:: http_get_handler(struct soap* soap)
  137. {
  138. if (soap == NULL || soap->user == NULL)
  139. {
  140. return SOAP_ERR;
  141. }
  142. Http::CRestServicePlugin* pThis = (CRestServicePlugin*)soap->user;
  143. return pThis->Process(soap,HTTP_GET);
  144. }
  145.  
  146. /* the text handler copies the message back */
  147. int CRestServicePlugin:: http_post_text_handler(struct soap *soap)
  148. {
  149. if (soap == NULL || soap->user == NULL)
  150. {
  151. return SOAP_ERR;
  152. }
  153. Http::CRestServicePlugin* pThis = (CRestServicePlugin*)soap->user;
  154. return pThis->Process(soap,HTTP_POST);
  155. }
  156.  
  157. int CRestServicePlugin::Process( struct soap* soap ,HTTP_METHOD method)
  158. {
  159. Request request;
  160. request.method = method;
  161. request.soap = soap;
  162. request._plugin = this;
  163.  
  164. std::tr1::function<int(Request& request)> *fun = NULL;
  165. {
  166. char* uri = query(soap);
  167. size_t hash_uri = Fnv_hash<>::hash(soap->path, uri? (uri-soap->path): strlen(soap->path));
  168.  
  169. std::lock_guard<std::mutex> guard(m_dataMt);
  170. std::map<size_t,RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
  171. if (iter != m_uriFunMap.end())
  172. {
  173. fun = &iter->second;
  174. }
  175. }
  176.  
  177. if(!request.ParseRequest() || fun==NULL)
  178. {
  179. return request.ReponseWithEnd(HTTP_STATUS_NOT_FOUND);
  180. }
  181. return (*fun)(request);
  182. }
  183.  
  184. //////////////////////////////////////////////////////////////////////////
  185. //Request
  186. const char* Request::GetURI( )
  187. {
  188. return soap->path;
  189. }
  190. bool Request::ParseRequest()
  191. {
  192. char *s;
  193. s = query(soap);
  194. int i = ;
  195. while (s && s[] != '\0' && i<QUERY_MAX_SIZE)
  196. {
  197. char *key = query_key(soap,&s);
  198. if (key == NULL)
  199. {
  200. continue;
  201. }
  202. char* val = query_val(soap,&s);
  203. if (val == NULL)
  204. {
  205. continue;
  206. }
  207.  
  208. _query[i].key = key;
  209. _query[i].value = val;
  210. ++i;
  211. }
  212.  
  213. if (i<QUERY_MAX_SIZE)
  214. {//最后一个初始化为空
  215. _query[i].key = NULL;
  216. }
  217.  
  218. return true;
  219. }
  220.  
  221. const char* Request::Query( const char* key)
  222. {
  223. if (key == NULL)
  224. {
  225. return NULL;
  226. }
  227.  
  228. int i = ;
  229. while (i<QUERY_MAX_SIZE && _query[i].key!=NULL)
  230. {
  231. if (strcmp(_query[i].key, key) == )
  232. {
  233. return _query[i].value;
  234. }
  235. ++i;
  236. }
  237.  
  238. return NULL;
  239. }
  240.  
  241. int Request::ReponseWithEnd( int code )
  242. {
  243. const char* res = NULL;
  244. switch(code)
  245. {
  246. case HTTP_STATUS_BAD_REQUEST:
  247. res = http_400;
  248. break;
  249. case HTTP_STATUS_NOT_FOUND:
  250. res = http_404;
  251. break;
  252. case HTTP_STATUS_SERVER_ERROR:
  253. res = http_500;
  254. break;
  255. default:
  256. res = http_unknow;
  257. break;
  258. }
  259. soap_send(soap,res);
  260. soap_end_send(soap);
  261.  
  262. return SOAP_OK;
  263. }
  264.  
  265. size_t Request::GetBody(char** body )
  266. {
  267. size_t len = ;
  268. if(SOAP_OK != soap_http_body(soap, body, &len))
  269. {
  270. return ;
  271. }
  272.  
  273. return len;
  274. }
  275.  
  276. //////////////////////////////////////////////////////////////////////////
  277. //response
  278. Response::Response()
  279. {
  280. _soap = NULL;
  281. _mod = RESPONSE_MODE_SYN;
  282. //soap->user = RESPONSE_MODE_SYN;
  283. _plugin = NULL;
  284. }
  285.  
  286. Response::Response(Request& req, int mod)
  287. {
  288. _soap = NULL;
  289.  
  290. BeginResponse(req, mod);
  291. }
  292.  
  293. Response::~Response()
  294. {
  295. EndResponse();
  296. }
  297.  
  298. void Response::SetContentType(const char* conttype)
  299. {
  300. _soap->http_content = conttype;
  301. }
  302.  
  303. int Response::Send(const char* data)
  304. {
  305. return Send(data, strlen(data));
  306. }
  307.  
  308. int Response::Send(const char* data, std::size_t len)
  309. {
  310. return soap_send_raw(_soap, data, len);
  311. }
  312.  
  313. int Response::BeginResponse(Request& req, int mod)
  314. {
  315. EndResponse();
  316.  
  317. _soap = req.soap;
  318. _mod = mod;
  319. _soap->user = (void*)_mod;
  320. _plugin = req._plugin;
  321.  
  322. return soap_response(_soap ,SOAP_FILE);
  323. }
  324.  
  325. int Response::EndResponse(void)
  326. {
  327. int ret = SOAP_OK;
  328. if (_soap == NULL)
  329. {
  330. return SOAP_OK;
  331. }
  332.  
  333. ret = soap_end_send(_soap);
  334.  
  335. if (_mod == RESPONSE_MODE_ASYN)
  336. {//如果是异步模式,需要释放
  337. soap_destroy(_soap);
  338. soap_end(_soap);
  339. if (_plugin->_funFreeSoap)
  340. {
  341. _plugin->_funFreeSoap(_soap);
  342. }
  343. else
  344. {
  345. soap_done(_soap);
  346. soap_free(_soap);
  347. }
  348. }
  349.  
  350. _soap = NULL;
  351. _mod = RESPONSE_MODE_SYN;
  352. _plugin = NULL;
  353.  
  354. return ret;
  355. }
  356.  
  357. }//namespace Http
  1. 8.使用例子
  1. #include "./web/SoapWebServer.h"
  2. #include "cJSON.h"
  3.  
  4. #include <thread>
  5.  
  6. bool static copy_file(Response* res, const char *name)
  7. {
  8. FILE *fd;
  9. size_t r;
  10. fd = fopen(name, "rb"); /* open file to copy */
  11. if (!fd)
  12. return false; /* return HTTP not found */
  13.  
  14. int tmpbuf_len = ;
  15. char *tmpbuf = new char[tmpbuf_len];
  16.  
  17. for (;;)
  18. {
  19. r = fread(tmpbuf, , tmpbuf_len, fd);
  20. if (!r)
  21. break;
  22. if (res->Send(tmpbuf, r))
  23. {//发送失败
  24. fclose(fd);
  25. return false;
  26. }
  27. //Sleep(70);
  28. }
  29. delete []tmpbuf;
  30. fclose(fd);
  31.  
  32. return true;
  33. }
  34.  
  35. void ThreadResponseImg(Response* res)
  36. {
  37. bool bret = false;
  38.  
  39. res->SetContentType("image/jpeg");
  40. bret = copy_file(res, "E:\\test\\testimage\\v1.jpg");
  41.  
  42. //printf("发送文件 %s\n", bret?"成功":"失败");
  43.  
  44. delete res;
  45. }
  46.  
  47. static int api_login(Request &req, void *user)
  48. {
  49. char * body = NULL;
  50. if (req.GetBody(&body))
  51. {
  52. printf("request login=%s\n", body);
  53. }
  54.  
  55. cJSON *jsonRes = NULL;
  56. jsonRes = cJSON_CreateObject();
  57. cJSON_AddNumberToObject(jsonRes, "errorCode", );
  58. cJSON_AddStringToObject(jsonRes, "token", "fd90bba04662411f86d8936900131936");
  59. char * str = cJSON_Print(jsonRes);
  60.  
  61. Response resp(req);
  62. resp.Send(str);
  63.  
  64. cJSON_Delete(jsonRes);
  65. free(str);
  66.  
  67. return ;
  68. }
  69.  
  70. class print_json
  71. {
  72. public:
  73. print_json()
  74. {
  75. //printf("cons print_json \n");
  76. }
  77. ~print_json()
  78. {
  79. printf("des print_json\n");
  80. }
  81. int print_person(Request &req)
  82. {
  83. Response res(req);
  84. res.SetContentType("application/json; charset=utf-8");
  85. res.Send("{\"print_person\" : 10}");
  86.  
  87. return ;
  88. }
  89.  
  90. int print_query(Request &req)
  91. {
  92. Response res(req);
  93. res.SetContentType("application/json; charset=utf-8");
  94. res.Send("{\"print_query\" : 10}");
  95.  
  96. /*for (rest_query_t *q = req.GetQuery(); q->key; ++q)
  97. {
  98. printf("key-%s,val-%s", q->key, q->value);
  99. }*/
  100. printf("\n");
  101.  
  102. return ;
  103. }
  104.  
  105. int print_img(Request &req)
  106. {
  107. Response *res = new Response;
  108. res->BeginResponse(req, RESPONSE_MODE_SYN);
  109.  
  110. ThreadResponseImg(res); //同步
  111.  
  112. //这里可以开启线程进行异步发送RESPONSE_MODE_ASYN
  113. //std::thread t1(ThreadResponseImg, res);
  114. //t1.detach();
  115.  
  116. return ;
  117. }
  118.  
  119. protected:
  120. private:
  121. };
  122.  
  123. int main(int argc, char* argv[])
  124. {
  125. print_json pt;
  126. CSoapWebServer web;
  127. const char* host = "0.0.0.0";
  128. unsigned port = ;
  129. web.StartService(host, port);
  130. printf("start listen %s:%u\n", host, port);
  131.  
  132. //tr1 bug 不能把bind作为参数传递
  133. //web.SetURI("/json", std::tr1::bind(&print_json::print, &pt, std::tr1::placeholders::_1));
  134. web.SetURI("/json", (RequestProcessFunction)std::tr1::bind(
  135. &print_json::print_person, &pt, std::tr1::placeholders::_1));
  136. web.SetURI("/json1", (RequestProcessFunction)std::tr1::bind(
  137. &print_json::print_query, &pt, std::tr1::placeholders::_1));
  138.  
  139. web.SetURI("/img", (RequestProcessFunction)std::tr1::bind(
  140. &print_json::print_img, &pt, std::tr1::placeholders::_1));
  141.  
  142. web.SetURI("/login", api_login, NULL);
  143.  
  144. getchar();
  145.  
  146. web.StopService();
  147.  
  148. return ;
  149. }

在浏览器中访问接口:
http://127.0.0.1:56789/json
这个接口返回json内容:

{"print_person" : 10}

http://127.0.0.1:56789/img
这个接口返回的是一张图片

利用gsoap库封装易用的rest框架的更多相关文章

  1. 人脸检测及识别python实现系列(5)——利用keras库训练人脸识别模型

    人脸检测及识别python实现系列(5)——利用keras库训练人脸识别模型 经过前面稍显罗嗦的准备工作,现在,我们终于可以尝试训练我们自己的卷积神经网络模型了.CNN擅长图像处理,keras库的te ...

  2. c# 利用动态库DllImport("kernel32")读写ini文件(提供Dmo下载)

    c# 利用动态库DllImport("kernel32")读写ini文件 自从读了设计模式,真的会改变一个程序员的习惯.我觉得嘛,经验也可以从一个人的习惯看得出来,看他的代码编写习 ...

  3. php学习笔记:利用gd库生成图片,并实现随机验证码

    说明:一些基本的代码我都进行了注释,这里实现的验证码位数.需要用的字符串都可以再设置.有我的注释,大家应该很容易能看得懂. 基本思路: 1.用mt_rand()随机生成数字确定需要获取的字符串,对字符 ...

  4. CocoaPods的安装及使用/利用开源库Diplomat实现分享及第三方登录/git的使用

    <<史上最简洁版本>> 1.gem sources -l查看 当前的源 //1.1 sudo -i..以下都是以管理员的身份来操作的 2.gem sources --remov ...

  5. 使用libzplay库封装一个音频类

    装载请说明原地址,谢谢~~      前两天我已经封装好一个duilib中使用的webkit内核的浏览器控件和一个基于vlc的用于播放视频的视频控件,这两个控件可以分别用在放酷狗播放器的乐库功能和MV ...

  6. 利用jdbc简单封装一个小框架(类似DBUtils)

    利用jdbc写的一个类似DBUtils的框架 package com.jdbc.orm.dbutils; import java.io.IOException; import java.io.Inpu ...

  7. python利用selenium库识别点触验证码

    利用selenium库和超级鹰识别点触验证码(学习于静谧大大的书,想自己整理一下思路) 一.超级鹰注册:超级鹰入口 1.首先注册一个超级鹰账号,然后在超级鹰免费测试地方可以关注公众号,领取1000积分 ...

  8. 利用OpenSSL库对Socket传输进行安全加密(RSA+AES)

    轉自:http://blog.chinaunix.net/uid-9543173-id-3921143.html 利用OpenSSL库对Socket传输进行安全加密(RSA+AES) 1. 利用RSA ...

  9. python3:利用smtplib库和smtp.qq.com邮件服务器发送邮件

    python3:利用smtplib库和smtp.qq.com邮件服务器发送邮件 使用qq的邮件服务器需要注意的两个地方主要是: 1.协议问题 使用465端口 SSL 协议 2.口令问题 出现SMTPA ...

随机推荐

  1. JTabbedPane的LookAndFeel--TabbedPaneUI

    在定制JTabbedPane的时候是需要使用到LookAndFeel的,而使用LookAndFeel定制的时候,其实主要是继承BasicTabbedPaneUI. to be continue...

  2. su 认证失败

    jiqing@ThinkPad:~$ su 密码: su:认证失败 jiqing@ThinkPad:~$ sudo passwd root [sudo] password for jiqing: 输入 ...

  3. securecrt中vim行号下划线问题及SecureCRT里root没有高亮的设置,修改linux终端命令行颜色

      背景:在用raspberry用SecureCRT下的vim打开文件时出现用set nu时行有下划线,于是找了下解决办法,如下:vim行号下划线问题在vim中发现开启显示行号(set number) ...

  4. pycharm打开多个项目并存

    问题: 有时我们需要打开多个项目,而现在的做法是:  原有的a项目不动,新打开一个pycharm来打开b项目, 或者 在原有的a项目中打开b项目并覆盖a项目,即a项目与b项目不能共存 需求: 有时我们 ...

  5. GitLab: API is not accessibl

    git push -u origin masterGitLab: API is not accessiblefatal: Could not read from remote repository. ...

  6. Python基础 — OS

    OS模块 -- 简介   OS模块是Python标准库中的一个用于访问操作系统功能的模块,OS模块提供了一种可移植的方法使用操作系统的功能.使用OS模块中提供的接口,可以实现跨平台访问.但是在OS模块 ...

  7. git clone ssh permissions are too open 解决方案。

    错误如图所示 方案如下 https://stackoverflow.com/questions/9270734/ssh-permissions-are-too-open-error

  8. NET 编程题

    1.C#编写创建一个线程的代码 using System; using System.IO; using System.Threading ; class MyThread{ public int c ...

  9. 使用JS分页 <span> beta 3.0 完成封装的分页

    <html> <head> <title>分页</title> <style> #titleDiv{ width:500px; backgr ...

  10. SparkContext, map, flatMap, zip以及例程wordcount

    SparkContext 通常作为入口函数,可以创建并返回一个RDD. 如把Spark集群当作服务端那Spark Driver就是客户端,SparkContext则是客户端的核心: 如注释所说 Spa ...