From 00f738a6170fba275a8805f64fc6eb5b34ba69c5 Mon Sep 17 00:00:00 2001 From: yanyiwu Date: Sat, 31 Jan 2015 10:14:16 +0800 Subject: [PATCH] update husky for server --- server/Husky/HttpReqInfo.hpp | 498 ++++++++++++++---------------- server/Husky/IRequestHandler.hpp | 18 +- server/Husky/NetUtils.hpp | 53 ++++ server/Husky/ThreadPoolServer.hpp | 133 ++------ server/Husky/WorkerThread.hpp | 215 ++++++------- 5 files changed, 412 insertions(+), 505 deletions(-) create mode 100644 server/Husky/NetUtils.hpp diff --git a/server/Husky/HttpReqInfo.hpp b/server/Husky/HttpReqInfo.hpp index 63bca91..4f5a811 100644 --- a/server/Husky/HttpReqInfo.hpp +++ b/server/Husky/HttpReqInfo.hpp @@ -6,288 +6,238 @@ #include "Limonp/Logger.hpp" #include "Limonp/StringUtil.hpp" -namespace Husky -{ - using namespace Limonp; - using namespace std; +namespace Husky { +using namespace Limonp; +using namespace std; - static const char* const KEY_METHOD = "METHOD"; - static const char* const KEY_PATH = "PATH"; - static const char* const KEY_PROTOCOL = "PROTOCOL"; +static const char* const KEY_METHOD = "METHOD"; +static const char* const KEY_URI = "URI"; +static const char* const KEY_PROTOCOL = "PROTOCOL"; - typedef unsigned char BYTE; +typedef unsigned char BYTE; - inline BYTE toHex(BYTE x) - { - return x > 9 ? x -10 + 'A': x + '0'; +inline BYTE toHex(BYTE x) { + return x > 9 ? x -10 + 'A': x + '0'; +} + +inline BYTE fromHex(BYTE x) { + return isdigit(x) ? x-'0' : x-'A'+10; +} + +inline void URLEncode(const string &sIn, string& sOut) { + for( size_t ix = 0; ix < sIn.size(); ix++ ) { + BYTE buf[4]; + memset( buf, 0, 4 ); + if( isalnum( (BYTE)sIn[ix] ) ) { + buf[0] = sIn[ix]; + } else { + buf[0] = '%'; + buf[1] = toHex( (BYTE)sIn[ix] >> 4 ); + buf[2] = toHex( (BYTE)sIn[ix] % 16); + } + sOut += (char *)buf; + } +}; + +inline void URLDecode(const string &sIn, string& sOut) { + for( size_t ix = 0; ix < sIn.size(); ix++ ) { + BYTE ch = 0; + if(sIn[ix]=='%') { + ch = (fromHex(sIn[ix+1])<<4); + ch |= fromHex(sIn[ix+2]); + ix += 2; + } else if(sIn[ix] == '+') { + ch = ' '; + } else { + ch = sIn[ix]; + } + sOut += (char)ch; + } +} + +class HttpReqInfo { + public: + HttpReqInfo() { + _isHeaderFinished = false; + _isBodyFinished = false; + _contentLength = 0; + } + public: + bool parseHeader(const string& buffer) { + return parseHeader(buffer.c_str(), buffer.size()); + } + bool parseHeader(const char* buffer, size_t len) { + string headerStr(buffer, len); + size_t lpos = 0, rpos = 0; + vector buf; + rpos = headerStr.find("\n", lpos); + if(string::npos == rpos) { + LogError("headerStr[%s] illegal.", headerStr.c_str()); + return false; + } + string firstline(headerStr, lpos, rpos - lpos); + trim(firstline); + if(!split(firstline, buf, " ") || 3 != buf.size()) { + LogError("parse header firstline[%s] failed.", firstline.c_str()); + return false; + } + _headerMap[KEY_METHOD] = trim(buf[0]); + _headerMap[KEY_URI] = trim(buf[1]); + _headerMap[KEY_PROTOCOL] = trim(buf[2]); + _parseUri(_headerMap[KEY_URI], _path, _methodGetMap); + + lpos = rpos + 1; + if(lpos >= headerStr.size()) { + LogError("headerStr[%s] illegal.", headerStr.c_str()); + return false; + } + //message header begin + while(lpos < headerStr.size() && string::npos != (rpos = headerStr.find('\n', lpos)) && rpos > lpos) { + string s(headerStr, lpos, rpos - lpos); + size_t p = s.find(':'); + if(string::npos == p) { + break;//encounter empty line + } + string k(s, 0, p); + string v(s, p+1); + trim(k); + trim(v); + if(k.empty()||v.empty()) { + LogError("headerStr[%s] illegal.", headerStr.c_str()); + return false; + } + upper(k); + _headerMap[k] = v; + lpos = rpos + 1; + } + rpos ++; + _isHeaderFinished = true; + string content_length; + if(!find("CONTENT-LENGTH", content_length)) { + _isBodyFinished = true; + return true; + } + _contentLength = atoi(content_length.c_str()); + if(rpos < headerStr.size()) { + appendBody(headerStr.c_str() + rpos, headerStr.size() - rpos); + } + return true; + //message header end + } + void appendBody(const char* buffer, size_t len) { + if(_isBodyFinished) { + return; + } + _body.append(buffer, len); + if(_body.size() >= _contentLength) { + _isBodyFinished = true; + } else { + _isBodyFinished = false; + } + } + bool isHeaderFinished() const { + return _isHeaderFinished; + } + bool isBodyFinished() const { + return _isBodyFinished; + } + public: + const string& set(const string& key, const string& value) { + return _headerMap[key] = value; + } + bool find(const string& key, string& res)const { + return _find(_headerMap, key, res); + } + bool GET(const string& argKey, string& res)const { + return _find(_methodGetMap, argKey, res); + } + //const string& getMethod() const + //{ + // return _headerMap.find(KEY_METHOD)->second; + //} + bool isGET() const { + string str; + if(!_find(_headerMap, KEY_METHOD, str)) { + return false; + } + return str == "GET"; + } + bool isPOST() const { + string str; + if(!_find(_headerMap, KEY_METHOD, str)) { + return false; + } + return str == "POST"; + } + const unordered_map & getMethodGetMap() const { + return _methodGetMap; + } + const unordered_map & getHeaders() const { + return _headerMap; + } + const string& getBody() const { + return _body; + } + const string& getPath() const { + return _path; + } + private: + bool _isHeaderFinished; + bool _isBodyFinished; + size_t _contentLength; + unordered_map _headerMap; + unordered_map _methodGetMap; + string _path; + string _body; + friend ostream& operator<<(ostream& os, const HttpReqInfo& obj); + private: + bool _find(const std::unordered_map& mp, const string& key, string& res)const { + std::unordered_map::const_iterator it = mp.find(key); + if(it == mp.end()) { + return false; + } + res = it->second; + return true; + } + private: + void _parseUri(const string& uri, string& path, std::unordered_map& mp) { + if(uri.empty()) { + return; } - inline BYTE fromHex(BYTE x) - { - return isdigit(x) ? x-'0' : x-'A'+10; + size_t pos = uri.find('?'); + path = uri.substr(0, pos); + if(string::npos == pos) { + return ; + } + size_t kleft = 0, kright = 0; + size_t vleft = 0, vright = 0; + for(size_t i = pos + 1; i < uri.size();) { + kleft = i; + while(i < uri.size() && uri[i] != '=') { + i++; + } + if(i >= uri.size()) { + break; + } + kright = i; + i++; + vleft = i; + while(i < uri.size() && uri[i] != '&' && uri[i] != ' ') { + i++; + } + vright = i; + mp[uri.substr(kleft, kright - kleft)] = uri.substr(vleft, vright - vleft); + i++; } - inline void URLEncode(const string &sIn, string& sOut) - { - for( size_t ix = 0; ix < sIn.size(); ix++ ) - { - BYTE buf[4]; - memset( buf, 0, 4 ); - if( isalnum( (BYTE)sIn[ix] ) ) - { - buf[0] = sIn[ix]; - } - else - { - buf[0] = '%'; - buf[1] = toHex( (BYTE)sIn[ix] >> 4 ); - buf[2] = toHex( (BYTE)sIn[ix] % 16); - } - sOut += (char *)buf; - } - }; + return; + } +}; - inline void URLDecode(const string &sIn, string& sOut) - { - for( size_t ix = 0; ix < sIn.size(); ix++ ) - { - BYTE ch = 0; - if(sIn[ix]=='%') - { - ch = (fromHex(sIn[ix+1])<<4); - ch |= fromHex(sIn[ix+2]); - ix += 2; - } - else if(sIn[ix] == '+') - { - ch = ' '; - } - else - { - ch = sIn[ix]; - } - sOut += (char)ch; - } - } - - class HttpReqInfo - { - public: - HttpReqInfo() - { - _isHeaderFinished = false; - _isBodyFinished = false; - _contentLength = 0; - } - public: - bool parseHeader(const char* buffer, size_t len) - { - string headerStr(buffer, len); - size_t lpos = 0, rpos = 0; - vector buf; - rpos = headerStr.find("\n", lpos); - if(string::npos == rpos) - { - LogError("headerStr[%s] illegal.", headerStr.c_str()); - return false; - } - string firstline(headerStr, lpos, rpos - lpos); - trim(firstline); - if(!split(firstline, buf, " ") || 3 != buf.size()) - { - LogError("parse header firstline[%s] failed.", firstline.c_str()); - return false; - } - _headerMap[KEY_METHOD] = trim(buf[0]); - _headerMap[KEY_PATH] = trim(buf[1]); - _headerMap[KEY_PROTOCOL] = trim(buf[2]); - //first request line end - //parse path to _methodGetMap - if("GET" == _headerMap[KEY_METHOD]) - { - _parseUrl(firstline, _methodGetMap); - } - - lpos = rpos + 1; - if(lpos >= headerStr.size()) - { - LogError("headerStr[%s] illegal.", headerStr.c_str()); - return false; - } - //message header begin - while(lpos < headerStr.size() && string::npos != (rpos = headerStr.find('\n', lpos)) && rpos > lpos) - { - string s(headerStr, lpos, rpos - lpos); - size_t p = s.find(':'); - if(string::npos == p) - { - break;//encounter empty line - } - string k(s, 0, p); - string v(s, p+1); - trim(k); - trim(v); - if(k.empty()||v.empty()) - { - LogError("headerStr[%s] illegal.", headerStr.c_str()); - return false; - } - upper(k); - _headerMap[k] = v; - lpos = rpos + 1; - } - rpos ++; - _isHeaderFinished = true; - string content_length; - if(!find("CONTENT-LENGTH", content_length)) - { - _isBodyFinished = true; - return true; - } - _contentLength = atoi(content_length.c_str()); - if(rpos < headerStr.size()) - { - appendBody(headerStr.c_str() + rpos, headerStr.size() - rpos); - } - return true; - //message header end - } - void appendBody(const char* buffer, size_t len) - { - if(_isBodyFinished) - { - return; - } - _body.append(buffer, len); - if(_body.size() >= _contentLength) - { - _isBodyFinished = true; - } - else - { - _isBodyFinished = false; - } - } - bool isHeaderFinished() const - { - return _isHeaderFinished; - } - bool isBodyFinished() const - { - return _isBodyFinished; - } - public: - const string& set(const string& key, const string& value) - { - return _headerMap[key] = value; - } - bool find(const string& key, string& res)const - { - return _find(_headerMap, key, res); - } - bool GET(const string& argKey, string& res)const - { - return _find(_methodGetMap, argKey, res); - } - //const string& getMethod() const - //{ - // return _headerMap.find(KEY_METHOD)->second; - //} - bool isGET() const - { - string str; - if(!_find(_headerMap, KEY_METHOD, str)) - { - return false; - } - return str == "GET"; - } - bool isPOST() const - { - string str; - if(!_find(_headerMap, KEY_METHOD, str)) - { - return false; - } - return str == "POST"; - } - const unordered_map & getMethodGetMap() const - { - return _methodGetMap; - } - const unordered_map & getHeaders() const - { - return _headerMap; - } - const string& getBody() const - { - return _body; - } - private: - bool _isHeaderFinished; - bool _isBodyFinished; - size_t _contentLength; - unordered_map _headerMap; - unordered_map _methodGetMap; - string _body; - friend ostream& operator<<(ostream& os, const HttpReqInfo& obj); - private: - bool _find(const std::unordered_map& mp, const string& key, string& res)const - { - std::unordered_map::const_iterator it = mp.find(key); - if(it == mp.end()) - { - return false; - } - res = it->second; - return true; - } - private: - bool _parseUrl(const string& url, std::unordered_map& mp) - { - if(url.empty()) - { - return false; - } - - size_t pos = url.find('?'); - if(string::npos == pos) - { - return false; - } - size_t kleft = 0, kright = 0; - size_t vleft = 0, vright = 0; - for(size_t i = pos + 1; i < url.size();) - { - kleft = i; - while(i < url.size() && url[i] != '=') - { - i++; - } - if(i >= url.size()) - { - break; - } - kright = i; - i++; - vleft = i; - while(i < url.size() && url[i] != '&' && url[i] != ' ') - { - i++; - } - vright = i; - mp[url.substr(kleft, kright - kleft)] = url.substr(vleft, vright - vleft); - i++; - } - - return true; - } - }; - - inline std::ostream& operator << (std::ostream& os, const Husky::HttpReqInfo& obj) - { - return os << obj._headerMap << obj._methodGetMap/* << obj._methodPostMap*/ << obj._body; - } +inline std::ostream& operator << (std::ostream& os, const Husky::HttpReqInfo& obj) { + return os << obj._headerMap << obj._methodGetMap/* << obj._methodPostMap*/ << obj._path << obj._body ; +} } diff --git a/server/Husky/IRequestHandler.hpp b/server/Husky/IRequestHandler.hpp index d1d857f..6e7522f 100644 --- a/server/Husky/IRequestHandler.hpp +++ b/server/Husky/IRequestHandler.hpp @@ -3,16 +3,14 @@ #include "HttpReqInfo.hpp" -namespace Husky -{ - class IRequestHandler - { - public: - virtual ~IRequestHandler(){}; - public: - virtual bool do_GET(const HttpReqInfo& httpReq, string& res) const = 0; - virtual bool do_POST(const HttpReqInfo& httpReq, string& res) const = 0; - }; +namespace Husky { +class IRequestHandler { + public: + virtual ~IRequestHandler() {}; + public: + virtual bool do_GET(const HttpReqInfo& httpReq, string& res) const = 0; + virtual bool do_POST(const HttpReqInfo& httpReq, string& res) const = 0; +}; } #endif diff --git a/server/Husky/NetUtils.hpp b/server/Husky/NetUtils.hpp new file mode 100644 index 0000000..1f713c9 --- /dev/null +++ b/server/Husky/NetUtils.hpp @@ -0,0 +1,53 @@ +#ifndef HUSKY_NET_UTILS_HPP +#define HUSKY_NET_UTILS_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Limonp/StdExtension.hpp" +#include "Limonp/HandyMacro.hpp" + +namespace Husky { +static const size_t LISTEN_QUEUE_LEN = 1024; + +typedef int SocketFd; +SocketFd CreateAndListenSocket(int port) { + SocketFd sock; + sock = socket(AF_INET, SOCK_STREAM, 0); + LIMONP_CHECK(sock != -1); + + int optval = 1; // nozero + int ret; + ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + LIMONP_CHECK(-1 != ret); + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + ret = ::bind(sock, (sockaddr*)&addr, sizeof(addr)); + LIMONP_CHECK(-1 != ret); + + ret = listen(sock, LISTEN_QUEUE_LEN); + LIMONP_CHECK(-1 != ret); + + return sock; +} + +const char* const HTTP_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: HuskyServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n%s"; +const char* const CHARSET_UTF8 = "UTF-8"; +} // namespace Husky + + +#endif diff --git a/server/Husky/ThreadPoolServer.hpp b/server/Husky/ThreadPoolServer.hpp index 8d21009..02a16d2 100644 --- a/server/Husky/ThreadPoolServer.hpp +++ b/server/Husky/ThreadPoolServer.hpp @@ -1,108 +1,39 @@ -#ifndef HUSKY_EPOLLSERVER_H -#define HUSKY_EPOLLSERVER_H +#ifndef HUSKY_THREADPOOLSERVER_H +#define HUSKY_THREADPOOLSERVER_H -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "NetUtils.hpp" #include "WorkerThread.hpp" -namespace Husky -{ - using namespace Limonp; +namespace Husky { +using namespace Limonp; - class ThreadPoolServer - { - private: - static const size_t LISTEN_QUEUE_LEN = 1024; +class ThreadPoolServer { + private: + ThreadPool _pool; + const IRequestHandler & _reqHandler; + int _host_socket; + public: + ThreadPoolServer(size_t thread_number, size_t queue_max_size, size_t port, const IRequestHandler & handler): + _pool(thread_number, queue_max_size), _reqHandler(handler), _host_socket(-1) { + _host_socket = CreateAndListenSocket(port); + } + ~ThreadPoolServer() {}; + public: + bool start() { + _pool.start(); + sockaddr_in clientaddr; + socklen_t nSize = sizeof(clientaddr); + int clientSock; - private: - ThreadPool _pool; - const IRequestHandler & _reqHandler; - int _host_socket; - public: - ThreadPoolServer(size_t thread_number, size_t queue_max_size, size_t port, const IRequestHandler & handler): - _pool(thread_number, queue_max_size), _reqHandler(handler), _host_socket(-1) - { - _init_host_socket(port); - }; - ~ThreadPoolServer(){}; - public: - bool start() - { - _pool.start(); - sockaddr_in clientaddr; - socklen_t nSize = sizeof(clientaddr); - int clientSock; - - while(true) - { - if(-1 == (clientSock = accept(_host_socket, (struct sockaddr*) &clientaddr, &nSize))) - { - LogError(strerror(errno)); - break; - //continue; - } - _pool.add(CreateTask(clientSock, _reqHandler)); - //_response(clientSock); - //_closesocket(clientSock); - - } - return true; - } - private: - bool _init_host_socket(size_t port) - { - _host_socket = socket(AF_INET, SOCK_STREAM, 0); - if(-1 == _host_socket) - { - LogFatal(strerror(errno)); - return false; - } - - int nRet = 1; - if(-1 == setsockopt(_host_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nRet, sizeof(nRet))) - { - LogFatal(strerror(errno)); - return false; - } - - struct sockaddr_in addrSock; - addrSock.sin_family = AF_INET; - addrSock.sin_port = htons(port); - addrSock.sin_addr.s_addr = htonl(INADDR_ANY); - if(-1 == ::bind(_host_socket, (sockaddr*)&addrSock, sizeof(sockaddr))) - { - LogFatal(strerror(errno)); - _closesocket(_host_socket); - return false; - } - if(-1 == listen(_host_socket, LISTEN_QUEUE_LEN)) - { - LogFatal(strerror(errno)); - return false; - } - - LogInfo("create socket listening port[%u] init ok", port); - return true; - } - void _closesocket(int sockfd) - { - if(-1 == close(sockfd)) - { - LogError(strerror(errno)); - return; - } - } - }; + while(true) { + if(-1 == (clientSock = accept(_host_socket, (struct sockaddr*) &clientaddr, &nSize))) { + LogError(strerror(errno)); + break; + } + _pool.add(CreateTask(clientSock, _reqHandler)); + } + return true; + } +}; } #endif diff --git a/server/Husky/WorkerThread.hpp b/server/Husky/WorkerThread.hpp index 37af949..3ef6114 100644 --- a/server/Husky/WorkerThread.hpp +++ b/server/Husky/WorkerThread.hpp @@ -3,131 +3,106 @@ #include "Limonp/ThreadPool.hpp" #include "IRequestHandler.hpp" +#include "NetUtils.hpp" -namespace Husky -{ - const char* const HTTP_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: HuskyServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n%s"; - const char* const CHARSET_UTF8 = "UTF-8"; - const char* const CLIENT_IP_K = "CLIENT_IP"; - const size_t RECV_BUFFER_SIZE = 16 * 1024; +namespace Husky { +const char* const CLIENT_IP_K = "CLIENT_IP"; +const size_t RECV_BUFFER_SIZE = 16 * 1024; - const struct linger LNG = {1, 1}; - const struct timeval SOCKET_TIMEOUT = {16, 0}; +const struct linger LNG = {1, 1}; +const struct timeval SOCKET_TIMEOUT = {16, 0}; + +class WorkerThread: public ITask { + public: + WorkerThread(int sockfs, const IRequestHandler& reqHandler): + _sockfd(sockfs), _reqHandler(reqHandler) { + } + virtual ~WorkerThread() { + } + private: + int _sockfd; + const IRequestHandler& _reqHandler; + + public: + void run() { + do { + if(!_setsockopt(_sockfd)) { + LogFatal("_getsockopt failed."); + break; + } + string strSnd, strRetByHandler; + HttpReqInfo httpReq; + if(!_receive(_sockfd, httpReq)) { + LogFatal("_receive failed."); + break; + } + + if(httpReq.isGET() && !_reqHandler.do_GET(httpReq, strRetByHandler)) { + LogError("do_GET failed."); + break; + } + if(httpReq.isPOST() && !_reqHandler.do_POST(httpReq, strRetByHandler)) { + LogError("do_POST failed."); + break; + } + strSnd = string_format(HTTP_FORMAT, CHARSET_UTF8, strRetByHandler.length(), strRetByHandler.c_str()); + + if(!_send(_sockfd, strSnd)) { + LogError("_send failed."); + break; + } + LogInfo("response:%s", strRetByHandler.c_str()); + } while(false); - class WorkerThread: public ITask - { - public: - WorkerThread(int sockfs, const IRequestHandler& reqHandler): - _sockfd(sockfs), _reqHandler(reqHandler) - { - } - virtual ~WorkerThread() - { - } - private: - int _sockfd; - const IRequestHandler& _reqHandler; + if(-1 == close(_sockfd)) { + LogError(strerror(errno)); + } + } + private: + bool _receive(int sockfd, HttpReqInfo& httpInfo) const { + char recvBuf[RECV_BUFFER_SIZE]; + int n = 0; + while(!httpInfo.isBodyFinished() && (n = recv(sockfd, recvBuf, RECV_BUFFER_SIZE, 0)) > 0) { + if(!httpInfo.isHeaderFinished()) { + if(!httpInfo.parseHeader(recvBuf, n)) { + LogError("parseHeader failed. "); + return false; + } + continue; + } + httpInfo.appendBody(recvBuf, n); + } + if(n < 0) { + LogError(strerror(errno)); + return false; + } + return true; + } + bool _send(int sockfd, const string& strSnd) const { + if(-1 == send(sockfd, strSnd.c_str(), strSnd.length(), 0)) { + LogError(strerror(errno)); + return false; + } + return true; + } + bool _setsockopt(int sockfd) const { + if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char*)&LNG, sizeof(LNG))) { + LogError(strerror(errno)); + return false; + } + if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) { + LogError(strerror(errno)); + return false; + } + if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) { + LogError(strerror(errno)); + return false; + } + return true; + } - public: - void run() - { - do - { - if(!_setsockopt(_sockfd)) - { - LogFatal("_setsockopt failed."); - break; - } - string strSnd, strRetByHandler; - HttpReqInfo httpReq; - if(!_receive(_sockfd, httpReq)) - { - LogFatal("_receive failed."); - break; - } - - if(httpReq.isGET() && !_reqHandler.do_GET(httpReq, strRetByHandler)) - { - LogError("do_GET failed."); - break; - } - if(httpReq.isPOST() && !_reqHandler.do_POST(httpReq, strRetByHandler)) - { - LogError("do_POST failed."); - break; - } - strSnd = string_format(HTTP_FORMAT, CHARSET_UTF8, strRetByHandler.length(), strRetByHandler.c_str()); - - if(!_send(_sockfd, strSnd)) - { - LogError("_send failed."); - break; - } - LogInfo("response:%s", strRetByHandler.c_str()); - } while(false); - - - if(-1 == close(_sockfd)) - { - LogError(strerror(errno)); - } - } - private: - bool _receive(int sockfd, HttpReqInfo& httpInfo) const - { - char recvBuf[RECV_BUFFER_SIZE]; - int n = 0; - while(!httpInfo.isBodyFinished() && (n = recv(sockfd, recvBuf, RECV_BUFFER_SIZE, 0)) > 0) - { - if(!httpInfo.isHeaderFinished()) - { - if(!httpInfo.parseHeader(recvBuf, n)) - { - LogError("parseHeader failed. "); - return false; - } - continue; - } - httpInfo.appendBody(recvBuf, n); - } - if(n < 0) - { - LogError(strerror(errno)); - return false; - } - return true; - } - bool _send(int sockfd, const string& strSnd) const - { - if(-1 == send(sockfd, strSnd.c_str(), strSnd.length(), 0)) - { - LogError(strerror(errno)); - return false; - } - return true; - } - bool _setsockopt(int sockfd) const - { - if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char*)&LNG, sizeof(LNG))) - { - LogError(strerror(errno)); - return false; - } - if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) - { - LogError(strerror(errno)); - return false; - } - if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) - { - LogError(strerror(errno)); - return false; - } - return true; - } - - }; +}; } #endif