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文件

 #ifndef SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__
#define SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__ #include <string>
#include <map>
#include <list>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread> using namespace std;
#include "stdsoap2.h"
#include "RestServicePlugin.h"
using namespace Http; class CSoapWebServer
{
public:
CSoapWebServer();
~CSoapWebServer(); static const int AcceptTimeout = ;//>单位s
static const int RecvTimeout = ;//>单位s
static const int SendTimeout = ;//>单位s
static const int MaxThreadCount = ;
static const unsigned int WaitTimeout = ; //>单位s
void SetURI(const char* URI,RequestProcessFunc fun, void * user);
void SetURI(const char* URI, RequestProcessFunction & fun);
void ResetURI(const char* URI);
void ClearURI(); bool StartService(const char* ip,unsigned int port);
void StopService(); protected:
struct THREAD_INFO
{
struct soap* soap_listen;
struct soap* soap_client;
CSoapWebServer* pThis;
};
bool StartThread();
void CloseThread(); void ServiceListenThread();
void ServiceServeThread(THREAD_INFO*pParam);
void Listen();
void ExecuteServe(THREAD_INFO* info);
int SoapServ(struct soap* soap); int BeginServe(struct soap* soap);
int EndServe(struct soap* soap); struct soap* PopSoap(void);
void PushSoap(struct soap* soap);
void FreeSoapAll(void);
private: CRestServicePlugin m_service;
struct soap* m_pSoap;
volatile bool m_bExit;
std::thread *m_ListenThread; //>接收线程句柄
std::thread *m_ServeThread[MaxThreadCount]; //>服务执行线程
struct CLIENT_INFO
{
SOAP_SOCKET socket;
unsigned long ip;
unsigned int port;
};
std::queue<CLIENT_INFO> m_acceptClientList;
std::queue<struct soap*> m_soapList;
std::mutex m_listMt;
std::condition_variable m_cvClient;
unsigned int m_iClientCount;
}; #endif // SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__
5.server.cpp文件
 #include "SoapWebServer.h"
//#include "soap.nsmap" SOAP_NMAC struct Namespace namespaces[] = {
{"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope", NULL},
{"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding", NULL},
{"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
{"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
{NULL, NULL, NULL, NULL}
}; int TestAPI(Request& request)
{
char* body = NULL;
size_t body_len = request.GetBody(&body); Response res(request);
res.SetContentType("text/json");
res.Send("{\"name\":\"bobo\",\"age\": 50}"); return SOAP_OK;
} CSoapWebServer::CSoapWebServer():
m_pSoap(NULL),
m_bExit(false),
m_ListenThread(nullptr),
m_iClientCount()
{
for (int i = ; i < MaxThreadCount; ++i)
{
m_ServeThread[i] = nullptr;
}
} CSoapWebServer::~CSoapWebServer()
{ }
void CSoapWebServer::ClearURI()
{
m_service.ClearURI();
} void CSoapWebServer::ResetURI( const char* URI )
{
if (URI)
{
m_service.UnRegisteURI(URI);
}
} void CSoapWebServer::SetURI( const char* URI,RequestProcessFunc fun, void * user)
{
if (!URI || !fun)
{
return;
} m_service.RegisteURI(URI,fun, user);
} void CSoapWebServer::SetURI(const char* URI, RequestProcessFunction & fun)
{
if (!URI || !fun)
{
return;
} m_service.RegisteURI(URI,fun);
} bool CSoapWebServer::StartService(const char* ip,unsigned int port)
{
//StopService();
m_bExit = false;
do
{
m_pSoap = soap_new();
if (NULL == m_pSoap)
{
break;
} soap_init1(m_pSoap, SOAP_C_UTFSTRING);
m_pSoap->bind_flags = SO_REUSEADDR;
m_pSoap->send_timeout = SendTimeout;
m_pSoap->recv_timeout = RecvTimeout;
m_pSoap->accept_timeout = AcceptTimeout;
m_pSoap->imode = SOAP_C_UTFSTRING; m_pSoap->namespaces = namespaces;
soap_set_local_namespaces(m_pSoap); m_service.Hook(m_pSoap);
{
FreeSoapFunction fun((FreeSoapFunction)std::tr1::bind(
&CSoapWebServer::PushSoap, this, std::tr1::placeholders::_1));
m_service.RegisterFreeSoap(fun);
} SOAP_SOCKET serverSocket = soap_bind(m_pSoap,ip,port,);
if (serverSocket == SOAP_INVALID_SOCKET)
{
printf("err soap_bind, %s:%u\n", ip, port);
break;
}
printf("soap bind %s:%u\n", ip, port); if (!StartThread())
{
printf("err StartThread\n");
break;
}
printf("start success\n");
return true;
} while (false);
printf("err start failed\n");
StopService();
return false;
}
void CSoapWebServer::StopService()
{
m_bExit = true;
CloseThread();
m_iClientCount = ; m_service.ClearURI();
FreeSoapAll();
if (NULL != m_pSoap)
{
soap_destroy(m_pSoap);
soap_end(m_pSoap);
soap_done(m_pSoap);
soap_free(m_pSoap);
m_pSoap = NULL;
}
}
bool CSoapWebServer::StartThread()
{
//>开启service接受执行线程
m_ListenThread = new std::thread(
&CSoapWebServer::ServiceListenThread,this); int iThreadCount = ;
if( iThreadCount > MaxThreadCount)
{
iThreadCount = MaxThreadCount;
}
else if(iThreadCount == )
{
iThreadCount = ;
} for (int i = ; i < iThreadCount; ++i)
{
soap* pSoap = soap_copy(m_pSoap);
THREAD_INFO* info = new(std::nothrow)THREAD_INFO;
if (info == NULL)
{
return false;
}
info->soap_listen = m_pSoap;
info->soap_client = pSoap;
info->pThis = this;
m_ServeThread[i] = new std::thread(
&CSoapWebServer::ServiceServeThread, this, info);
}
return true;
} void CSoapWebServer::CloseThread()
{
m_cvClient.notify_all();
if (m_ListenThread)
{
m_ListenThread->join();
delete m_ListenThread;
m_ListenThread = nullptr;
} for (int i = ; i < MaxThreadCount; i++)
{
if(m_ServeThread[i])
{
m_ServeThread[i]->join();
delete m_ServeThread[i];
m_ServeThread[i] = nullptr;
}
}
}
void CSoapWebServer::ServiceListenThread()
{
Listen();
return ;
}
void CSoapWebServer::Listen()
{
if (NULL == m_pSoap)
{
return ;
}
CLIENT_INFO clientInfo;
while (!m_bExit)
{
clientInfo.socket = soap_accept(m_pSoap);
if (clientInfo.socket != SOAP_INVALID_SOCKET )
{
std::unique_lock<std::mutex> guard(m_listMt);
clientInfo.ip = m_pSoap->ip;
clientInfo.port = m_pSoap->port;
m_acceptClientList.push(clientInfo);
++m_iClientCount;
m_cvClient.notify_one();
}
}
} void CSoapWebServer::ServiceServeThread(THREAD_INFO* pParam )
{
if (NULL == pParam)
{
return ;
}
THREAD_INFO* info = (THREAD_INFO*)pParam;
CSoapWebServer *pThis = info->pThis; if(NULL == pThis)
{
return ;
}
ExecuteServe(info); delete info; return ;
}
void CSoapWebServer::ExecuteServe(THREAD_INFO* info )
{
const int iTempSockCount = ;
CLIENT_INFO tempClientArr[iTempSockCount] = {};
int end_pos = ;
struct soap* soap = NULL; soap = info->soap_client;
int ret = SOAP_OK; while (!m_bExit)
{
{
std::unique_lock<std::mutex> guard(m_listMt);
if (m_acceptClientList.empty())
{
m_cvClient.wait(guard);
}
for (end_pos=;
end_pos<iTempSockCount && !m_acceptClientList.empty();
++end_pos )
{
tempClientArr[end_pos] = m_acceptClientList.front();
m_acceptClientList.pop();
--m_iClientCount;
}
} for (int i = ; i < end_pos; ++i)
{
soap->socket = tempClientArr[i].socket;
soap->ip = tempClientArr[i].ip;
soap->port = tempClientArr[i].port;
if(!soap_valid_socket(soap->socket))
{
continue;
} if ((ret=BeginServe(soap)) != SOAP_OK)
{
//printf("serve error.code:%d msg:%s\n", soap->error,*(soap_faultstring(soap)));
} if (ret == SOAP_STOP/*(int)soap->user == RESPONSE_MODE_ASYN*/)
{//异步
//获取一个soap
soap = PopSoap();
if (soap == NULL)
{//缓存没有,拷贝一个
soap = soap_copy(info->soap_listen);
}
}
else
{
EndServe(soap);
} soap_destroy(soap);
soap_end(soap);
}
} //回收
PushSoap(soap);
} int CSoapWebServer::SoapServ( struct soap* soap )
{
#ifndef WITH_FASTCGI
unsigned int k = soap->max_keep_alive;
#endif
do
{
#ifndef WITH_FASTCGI
if (soap->max_keep_alive > && !--k)
{
soap->keep_alive = ;
}
#endif
if (soap_begin_serve(soap))
{
if (soap->error >= SOAP_STOP)
{
continue;
}
return soap->error;
} #ifdef WITH_FASTCGI
soap_destroy(soap);
soap_end(soap);
} while ();
#else
} while (soap->keep_alive);
#endif
return SOAP_OK;
} int CSoapWebServer::BeginServe(struct soap* soap)
{
void * user = soap->user;
long ret = RESPONSE_MODE_SYN; soap_begin(soap);
if (soap_begin_recv(soap)
|| soap_envelope_begin_in(soap)
|| soap_recv_header(soap)
|| soap_body_begin_in(soap))
{ if (soap->error < SOAP_STOP)
{
#ifdef WITH_FASTCGI
(void)soap_send_fault(soap);
#else
return soap_send_fault(soap);
#endif
}
} ret = (long)soap->user;
soap->user = user; return (ret==RESPONSE_MODE_ASYN) ? SOAP_STOP: SOAP_OK;
} int CSoapWebServer::EndServe(struct soap* soap)
{
return soap_closesock(soap);
} struct soap* CSoapWebServer::PopSoap(void)
{
struct soap * soap = NULL;
std::unique_lock<std::mutex> guard(m_listMt);
if (m_soapList.empty())
{
return NULL;
}
soap = m_soapList.front();
m_soapList.pop(); return soap;
} void CSoapWebServer::PushSoap(struct soap* soap)
{
if (soap == NULL)
{
return ;
} std::unique_lock<std::mutex> guard(m_listMt);
m_soapList.push(soap);
} void CSoapWebServer::FreeSoapAll(void)
{
std::queue<struct soap*> lsoap;
{
std::unique_lock<std::mutex> guard(m_listMt);
lsoap = m_soapList;
while (!m_soapList.empty())
{
m_soapList.pop();
}
} struct soap * soap;
while (!lsoap.empty())
{
soap = lsoap.front(); soap_destroy(soap);
soap_end(soap); soap_done(soap);
soap_free(soap); lsoap.pop();
}
}

6.插件头文件

 #ifndef RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__
#define RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__ #include <string>
#include <map>
#include <mutex> #if (defined _WIN32 || defined _WIN64)
# include <memory> //shared_ptr
# include <functional>
#elif defined(__linux__)
# include <tr1/memory>
# include <tr1/functional>
#endif #include "stdsoap2.h"
#include "httpget.h"
#include "httppost.h" namespace Http
{
class CRestServicePlugin;
class Request; typedef int (*RequestProcessFunc)(Request& request, void* user);
typedef std::tr1::function<int(Request& request)> RequestProcessFunction;
typedef std::tr1::function<void(struct soap*)> FreeSoapFunction; enum HTTP_STATUS
{
HTTP_STATUS_OK = ,
HTTP_STATUS_BAD_REQUEST = , // invalid syntax
HTTP_STATUS_DENIED = , // access denied
HTTP_STATUS_PAYMENT_REQ = , // payment required
HTTP_STATUS_FORBIDDEN = , // request forbidden
HTTP_STATUS_NOT_FOUND = , // object not found
HTTP_STATUS_BAD_METHOD = , // method is not allowed
HTTP_STATUS_NONE_ACCEPTABLE = , // no response acceptable to client found
HTTP_STATUS_PROXY_AUTH_REQ = , // proxy authentication required
HTTP_STATUS_REQUEST_TIMEOUT = , // server timed out waiting for request
HTTP_STATUS_CONFLICT = , // user should resubmit with more info
HTTP_STATUS_GONE = , // the resource is no longer available
HTTP_STATUS_LENGTH_REQUIRED = , // the server refused to accept request w/o a length
HTTP_STATUS_PRECOND_FAILED = , // precondition given in request failed
HTTP_STATUS_REQUEST_TOO_LARGE = , // request entity was too large
HTTP_STATUS_URI_TOO_LONG = , // request URI too long
HTTP_STATUS_UNSUPPORTED_MEDIA = , // unsupported media type
HTTP_STATUS_RETRY_WITH = , // retry after doing the appropriate action. HTTP_STATUS_SERVER_ERROR = ,// internal server error
HTTP_STATUS_NOT_SUPPORTED = , // required not supported
HTTP_STATUS_BAD_GATEWAY = , // error response received from gateway
HTTP_STATUS_SERVICE_UNAVAIL = , // temporarily overloaded
HTTP_STATUS_GATEWAY_TIMEOUT = , // timed out waiting for gateway
HTTP_STATUS_VERSION_NOT_SUP = // HTTP version not supported
}; enum HTTP_METHOD
{
HTTP_GET = ,
HTTP_POST =
};
enum HTTP_RES_TYPE
{
HTTP_HTML = ,
HTTP_FILE =
};
typedef struct rest_str_s
{
size_t len; //字符串长度
char* ptr; //字符串首地址
}rest_str_t; typedef struct rest_query_s
{
const char* key;
const char* value;
}rest_query_t; static const size_t QUERY_MAX_SIZE = ; //最多参数个数 class Request
{
friend class CRestServicePlugin;
friend class Response;
public:
Request()
{
soap = NULL;
} /** @fn Query
* @brief 获取url中的请求参数
* @param key:
* @return 返回查询到的值
*/
const char* Query( const char* key); /** @fn GetBody
* @brief 获取请求体
* @param
* @return 请求内容字节数,0为空
*/
size_t GetBody(char** body); HTTP_METHOD GetMethod(void){ return method;} protected:
/** @fn GetURI
* @brief 获取请求的url
* @param
* @return
*/
const char* GetURI(); int ReponseWithEnd(int code);
/************************************
>@ Method: ParseRequest
>@ FullName: Http::Request::ParseRequest
>@ Brief: 解析请求参数
>@ Access: public
>@ Returns: bool
>@ Qualifier:
************************************/
bool ParseRequest(); rest_query_t* GetQuery(void){return _query;} private:
rest_query_t _query[QUERY_MAX_SIZE];//请求参数
HTTP_METHOD method;
struct soap* soap;
CRestServicePlugin * _plugin;
}; #define RESPONSE_MODE_SYN 0 //同步
#define RESPONSE_MODE_ASYN 1 //异步 class Response
{
public:
Response(Request& req, int mod=RESPONSE_MODE_SYN);
Response();
~Response(); /** @fn SetContentType
* @brief 设置响应内容,默认为空,例如"text/json"
* @param
* @return
*/
void SetContentType(const char* conttype); /** @fn Send
* @brief 发送响应数据,可以调用多次发送
* @param
* @return 0-发送成功
*/
int Send(const char* data);
int Send(const char* data, std::size_t len); /** @fn BeginResponse
* @brief 开始响应
* @param mod:响应模式,RESPONSE_MODE_SYN-同步,RESPONSE_MODE_ASYN-异步
* @return
*/
int BeginResponse(Request& req, int mod=RESPONSE_MODE_SYN);
int EndResponse(void); protected: private:
struct soap * _soap;
int _mod;
CRestServicePlugin *_plugin;
}; class CRestServicePlugin
{
friend class Response;
public:
CRestServicePlugin(void);
~CRestServicePlugin(void); static int http_get_handler(struct soap*);
static int http_post_text_handler(struct soap *soap);
public:
bool Hook(struct soap* soap);
void RegisteURI(const char* URI,RequestProcessFunc fun, void* user);
void RegisteURI(const char* URI, RequestProcessFunction & fun);
void UnRegisteURI(const char* URI);
void ClearURI(); void RegisterFreeSoap(FreeSoapFunction & fun);
protected:
int Process(struct soap* soap,HTTP_METHOD method);
private:
std::mutex m_dataMt;
//uri的处理函数映射表
std::map<std::size_t,RequestProcessFunction> m_uriFunMap;
FreeSoapFunction _funFreeSoap;
};
} #endif // RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__
7.插件cpp文件
 #include "RestServicePlugin.h"
#include "httpget.h" namespace Http
{
static const char* json_type = "application/json";
static const char* http_unknow = "HTTP/1.1 -1 UNKNOW\r\nConnection: close\r\n\r\n";
static const char* http_400 = "HTTP/1.1 400 BAD REQUEST\r\nConnection: close\r\n\r\n";
static const char* http_404 = "HTTP/1.1 404 NOT FOUND\r\nConnection: close\r\n\r\n";
static const char* http_500 = "HTTP/1.1 500 SERVER ERROR\r\nConnection: close\r\n\r\n"; //FNV hash copy from gcc
// Dummy generic implementation (for sizeof(size_t) != 4, 8).
template<std::size_t = sizeof(std::size_t)>
struct Fnv_hash
{
static std::size_t
hash(const char* first, std::size_t length)
{
std::size_t result = ;
for (; length > ; --length)
result = (result * ) + *first++;
return result;
}
}; template<>
struct Fnv_hash<>
{
static std::size_t
hash(const char* first, std::size_t length)
{
std::size_t result = static_cast<std::size_t>(2166136261UL);
for (; length > ; --length)
{
result ^= (std::size_t)*first++;
result *= 16777619UL;
}
return result;
}
}; template<>
struct Fnv_hash<>
{
static std::size_t
hash(const char* first, std::size_t length)
{
std::size_t result = static_cast<std::size_t>(14695981039346656037ULL);
for (; length > ; --length)
{
result ^= (std::size_t)*first++;
result *= 1099511628211ULL;
}
return result;
}
}; http_post_handlers handlers[] =
{
{ "POST", Http::CRestServicePlugin::http_post_text_handler },
{ NULL }
}; //////////////////////////////////////////////////////////////////////////
//CRestServicePlugin
CRestServicePlugin::CRestServicePlugin(void) {
} CRestServicePlugin::~CRestServicePlugin(void)
{
} bool CRestServicePlugin::Hook( struct soap* soap )
{
if (NULL == soap)
{
return false;
}
soap->user = (void*)this;
soap_register_plugin_arg(soap, http_get, (void*)http_get_handler);
soap_register_plugin_arg(soap,http_post,(void*)handlers);
return true;
} void CRestServicePlugin::RegisteURI( const char* URI,RequestProcessFunc fun , void* user)
{
std::tr1::function<int(Request& request)> funl;
funl = std::tr1::bind(fun, std::tr1::placeholders::_1, user); RegisteURI(URI, funl);
} void CRestServicePlugin::RegisteURI(const char* URI, RequestProcessFunction & fun)
{
size_t hash_uri = Fnv_hash<>::hash(URI, strlen(URI)); std::lock_guard<std::mutex> guard(m_dataMt);
std::map<size_t, RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
if (iter != m_uriFunMap.end())
{
iter->second = fun;
}
else
{
m_uriFunMap.insert(std::map<size_t,RequestProcessFunction>::value_type(hash_uri,fun));
}
} void CRestServicePlugin::RegisterFreeSoap(FreeSoapFunction & fun)
{
_funFreeSoap = fun;
} void CRestServicePlugin::UnRegisteURI( const char* URI )
{
size_t hash_uri = Fnv_hash<>::hash(URI, strlen(URI)); std::lock_guard<std::mutex> guard(m_dataMt);
std::map<size_t,RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
if (iter != m_uriFunMap.end())
{
m_uriFunMap.erase(iter);
}
} void CRestServicePlugin::ClearURI()
{
std::lock_guard<std::mutex> guard(m_dataMt);
m_uriFunMap.clear();
_funFreeSoap = NULL;
} int CRestServicePlugin:: http_get_handler(struct soap* soap)
{
if (soap == NULL || soap->user == NULL)
{
return SOAP_ERR;
}
Http::CRestServicePlugin* pThis = (CRestServicePlugin*)soap->user;
return pThis->Process(soap,HTTP_GET);
} /* the text handler copies the message back */
int CRestServicePlugin:: http_post_text_handler(struct soap *soap)
{
if (soap == NULL || soap->user == NULL)
{
return SOAP_ERR;
}
Http::CRestServicePlugin* pThis = (CRestServicePlugin*)soap->user;
return pThis->Process(soap,HTTP_POST);
} int CRestServicePlugin::Process( struct soap* soap ,HTTP_METHOD method)
{
Request request;
request.method = method;
request.soap = soap;
request._plugin = this; std::tr1::function<int(Request& request)> *fun = NULL;
{
char* uri = query(soap);
size_t hash_uri = Fnv_hash<>::hash(soap->path, uri? (uri-soap->path): strlen(soap->path)); std::lock_guard<std::mutex> guard(m_dataMt);
std::map<size_t,RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
if (iter != m_uriFunMap.end())
{
fun = &iter->second;
}
} if(!request.ParseRequest() || fun==NULL)
{
return request.ReponseWithEnd(HTTP_STATUS_NOT_FOUND);
}
return (*fun)(request);
} //////////////////////////////////////////////////////////////////////////
//Request
const char* Request::GetURI( )
{
return soap->path;
}
bool Request::ParseRequest()
{
char *s;
s = query(soap);
int i = ;
while (s && s[] != '\0' && i<QUERY_MAX_SIZE)
{
char *key = query_key(soap,&s);
if (key == NULL)
{
continue;
}
char* val = query_val(soap,&s);
if (val == NULL)
{
continue;
} _query[i].key = key;
_query[i].value = val;
++i;
} if (i<QUERY_MAX_SIZE)
{//最后一个初始化为空
_query[i].key = NULL;
} return true;
} const char* Request::Query( const char* key)
{
if (key == NULL)
{
return NULL;
} int i = ;
while (i<QUERY_MAX_SIZE && _query[i].key!=NULL)
{
if (strcmp(_query[i].key, key) == )
{
return _query[i].value;
}
++i;
} return NULL;
} int Request::ReponseWithEnd( int code )
{
const char* res = NULL;
switch(code)
{
case HTTP_STATUS_BAD_REQUEST:
res = http_400;
break;
case HTTP_STATUS_NOT_FOUND:
res = http_404;
break;
case HTTP_STATUS_SERVER_ERROR:
res = http_500;
break;
default:
res = http_unknow;
break;
}
soap_send(soap,res);
soap_end_send(soap); return SOAP_OK;
} size_t Request::GetBody(char** body )
{
size_t len = ;
if(SOAP_OK != soap_http_body(soap, body, &len))
{
return ;
} return len;
} //////////////////////////////////////////////////////////////////////////
//response
Response::Response()
{
_soap = NULL;
_mod = RESPONSE_MODE_SYN;
//soap->user = RESPONSE_MODE_SYN;
_plugin = NULL;
} Response::Response(Request& req, int mod)
{
_soap = NULL; BeginResponse(req, mod);
} Response::~Response()
{
EndResponse();
} void Response::SetContentType(const char* conttype)
{
_soap->http_content = conttype;
} int Response::Send(const char* data)
{
return Send(data, strlen(data));
} int Response::Send(const char* data, std::size_t len)
{
return soap_send_raw(_soap, data, len);
} int Response::BeginResponse(Request& req, int mod)
{
EndResponse(); _soap = req.soap;
_mod = mod;
_soap->user = (void*)_mod;
_plugin = req._plugin; return soap_response(_soap ,SOAP_FILE);
} int Response::EndResponse(void)
{
int ret = SOAP_OK;
if (_soap == NULL)
{
return SOAP_OK;
} ret = soap_end_send(_soap); if (_mod == RESPONSE_MODE_ASYN)
{//如果是异步模式,需要释放
soap_destroy(_soap);
soap_end(_soap);
if (_plugin->_funFreeSoap)
{
_plugin->_funFreeSoap(_soap);
}
else
{
soap_done(_soap);
soap_free(_soap);
}
} _soap = NULL;
_mod = RESPONSE_MODE_SYN;
_plugin = NULL; return ret;
} }//namespace Http
8.使用例子
 #include "./web/SoapWebServer.h"
#include "cJSON.h" #include <thread> bool static copy_file(Response* res, const char *name)
{
FILE *fd;
size_t r;
fd = fopen(name, "rb"); /* open file to copy */
if (!fd)
return false; /* return HTTP not found */ int tmpbuf_len = ;
char *tmpbuf = new char[tmpbuf_len]; for (;;)
{
r = fread(tmpbuf, , tmpbuf_len, fd);
if (!r)
break;
if (res->Send(tmpbuf, r))
{//发送失败
fclose(fd);
return false;
}
//Sleep(70);
}
delete []tmpbuf;
fclose(fd); return true;
} void ThreadResponseImg(Response* res)
{
bool bret = false; res->SetContentType("image/jpeg");
bret = copy_file(res, "E:\\test\\testimage\\v1.jpg"); //printf("发送文件 %s\n", bret?"成功":"失败"); delete res;
} static int api_login(Request &req, void *user)
{
char * body = NULL;
if (req.GetBody(&body))
{
printf("request login=%s\n", body);
} cJSON *jsonRes = NULL;
jsonRes = cJSON_CreateObject();
cJSON_AddNumberToObject(jsonRes, "errorCode", );
cJSON_AddStringToObject(jsonRes, "token", "fd90bba04662411f86d8936900131936");
char * str = cJSON_Print(jsonRes); Response resp(req);
resp.Send(str); cJSON_Delete(jsonRes);
free(str); return ;
} class print_json
{
public:
print_json()
{
//printf("cons print_json \n");
}
~print_json()
{
printf("des print_json\n");
}
int print_person(Request &req)
{
Response res(req);
res.SetContentType("application/json; charset=utf-8");
res.Send("{\"print_person\" : 10}"); return ;
} int print_query(Request &req)
{
Response res(req);
res.SetContentType("application/json; charset=utf-8");
res.Send("{\"print_query\" : 10}"); /*for (rest_query_t *q = req.GetQuery(); q->key; ++q)
{
printf("key-%s,val-%s", q->key, q->value);
}*/
printf("\n"); return ;
} int print_img(Request &req)
{
Response *res = new Response;
res->BeginResponse(req, RESPONSE_MODE_SYN); ThreadResponseImg(res); //同步 //这里可以开启线程进行异步发送RESPONSE_MODE_ASYN
//std::thread t1(ThreadResponseImg, res);
//t1.detach(); return ;
} protected:
private:
}; int main(int argc, char* argv[])
{
print_json pt;
CSoapWebServer web;
const char* host = "0.0.0.0";
unsigned port = ;
web.StartService(host, port);
printf("start listen %s:%u\n", host, port); //tr1 bug 不能把bind作为参数传递
//web.SetURI("/json", std::tr1::bind(&print_json::print, &pt, std::tr1::placeholders::_1));
web.SetURI("/json", (RequestProcessFunction)std::tr1::bind(
&print_json::print_person, &pt, std::tr1::placeholders::_1));
web.SetURI("/json1", (RequestProcessFunction)std::tr1::bind(
&print_json::print_query, &pt, std::tr1::placeholders::_1)); web.SetURI("/img", (RequestProcessFunction)std::tr1::bind(
&print_json::print_img, &pt, std::tr1::placeholders::_1)); web.SetURI("/login", api_login, NULL); getchar(); web.StopService(); return ;
}

在浏览器中访问接口:
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. 【bzoj1798】[Ahoi2009]Seq 维护序列seq

    大意:一个数组,三个操作,第一种是区间[a,b]每个数乘乘,第二种是区间[a,b]每个数加c,第三种是查询[a,b]区间的和并对p取摸. 两种操作就不能简单的只往下传标记.每次传乘法标记时,要把加法标 ...

  2. YTU 2517: 打倒魔王↖(^ω^)↗

    2517: 打倒魔王↖(^ω^)↗ 时间限制: 1 Sec  内存限制: 128 MB 提交: 231  解决: 112 题目描述 从前有一个王子,他喜欢上了邻国的一个公主.终于有一天他向公主表白了, ...

  3. mysql自增主键在大量删除后如何重新设置避免断层

    alter table tt auto_increment=8; 表tt mysql> select * from tt; +----+ | id | +----+ | 1 | | 2 | | ...

  4. Groonga开源搜索引擎——列存储做聚合,没有内建分布式,分片和副本是随mysql或者postgreSQL作为存储引擎由MySQL自身来做分片和副本的

    1. Characteristics of Groonga ppt:http://mroonga.org/publication/presentation/groonga-mysqluc2011.pd ...

  5. MySQL 基础 —— 数据类型、各种变量

    1. 基本数据类型 char:prod_id char(10),括号内的内容表示字符的长度 decimal:十进制,不带参数为整数(四舍五入) text:文本类型,长度不限 2. 日期和时间处理函数 ...

  6. NOIP 2011 Mayan游戏 大暴搜

    题目链接:https://www.luogu.org/problemnew/show/P1312 我的第一篇题解!! 当然感谢ZAGER 的提示,他的链接https://www.cnblogs.com ...

  7. 2-3 Vue实例中的数据,事件和方法

    上节课模板是写在Vue的实例里面的,现在我们可以把它恢复出来.写在挂载点的内部,看起来会舒服一点.Vue的数据项,可以配置任意的数据名字. <!DOCTYPE html> <html ...

  8. bzoj 1044: [HAOI2008]木棍分割【二分+dp】

    对于第一问二分然后贪心判断即可 对于第二问,设f[i][j]为已经到j为止砍了i段,转移的话从$$ f[i][j]=\sigema f[k][j-1] (s[j]-s[k-1]<=ans) 这里 ...

  9. robotframework - selenium 分层思路

    前言: 对于每一条用例来说,调用“百度搜索”关键字,输入搜索内容,输入预期结果即可.不同关心用例是如何执行的.如果百度输入框的定位发生了变化,只用去修改“百度搜索”关键字即可,不用对每一条用例做任何修 ...

  10. mysql——免安装配置

    1.下载 (1)下载地址:https://dev.mysql.com/downloads/mysql/ (2)选择下载 2.配置环境变量 (1)解压目录:D:\mysql-8.0.16-winx64 ...