首页 技术 正文
技术 2022年11月15日
0 收藏 671 点赞 4,881 浏览 20890 个字

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
这个接口返回的是一张图片

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,914
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,438
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,252
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,063
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,698
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,734