mirror of
https://github.com/yanyiwu/cppjieba.git
synced 2025-07-18 00:00:12 +08:00
update husky to version v0.2.0
This commit is contained in:
parent
194550823f
commit
484ce39d36
@ -1,107 +0,0 @@
|
|||||||
#ifndef HUSKY_WORKER_HPP
|
|
||||||
#define HUSKY_WORKER_HPP
|
|
||||||
|
|
||||||
#include "limonp/ThreadPool.hpp"
|
|
||||||
#include "IRequestHandler.hpp"
|
|
||||||
#include "NetUtils.hpp"
|
|
||||||
|
|
||||||
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};
|
|
||||||
|
|
||||||
class WorkerThread: public ITask {
|
|
||||||
public:
|
|
||||||
WorkerThread(int sockfs, IRequestHandler& reqHandler):
|
|
||||||
_sockfd(sockfs), _reqHandler(reqHandler) {
|
|
||||||
}
|
|
||||||
virtual ~WorkerThread() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void run() {
|
|
||||||
do {
|
|
||||||
if(!_setsockopt(_sockfd)) {
|
|
||||||
LogError("_getsockopt failed.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
string strSnd, strRetByHandler;
|
|
||||||
HttpReqInfo httpReq;
|
|
||||||
if(!_receive(_sockfd, httpReq)) {
|
|
||||||
LogError("_receive failed.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(httpReq.isGET() && !_reqHandler.doGET(httpReq, strRetByHandler)) {
|
|
||||||
LogError("doGET failed.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(httpReq.isPOST() && !_reqHandler.doPOST(httpReq, strRetByHandler)) {
|
|
||||||
LogError("doPOST 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;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
int _sockfd;
|
|
||||||
IRequestHandler& _reqHandler;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "limonp/Logger.hpp"
|
#include "limonp/Logging.hpp"
|
||||||
#include "limonp/StringUtil.hpp"
|
#include "limonp/StringUtil.hpp"
|
||||||
|
|
||||||
namespace husky {
|
namespace husky {
|
||||||
@ -16,11 +16,11 @@ static const char* const KEY_PROTOCOL = "PROTOCOL";
|
|||||||
|
|
||||||
typedef unsigned char BYTE;
|
typedef unsigned char BYTE;
|
||||||
|
|
||||||
inline BYTE toHex(BYTE x) {
|
inline BYTE ToHex(BYTE x) {
|
||||||
return x > 9 ? x -10 + 'A': x + '0';
|
return x > 9 ? x -10 + 'A': x + '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BYTE fromHex(BYTE x) {
|
inline BYTE FromHex(BYTE x) {
|
||||||
return isdigit(x) ? x-'0' : x-'A'+10;
|
return isdigit(x) ? x-'0' : x-'A'+10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,8 +32,8 @@ inline void URLEncode(const string &sIn, string& sOut) {
|
|||||||
buf[0] = sIn[ix];
|
buf[0] = sIn[ix];
|
||||||
} else {
|
} else {
|
||||||
buf[0] = '%';
|
buf[0] = '%';
|
||||||
buf[1] = toHex( (BYTE)sIn[ix] >> 4 );
|
buf[1] = ToHex( (BYTE)sIn[ix] >> 4 );
|
||||||
buf[2] = toHex( (BYTE)sIn[ix] % 16);
|
buf[2] = ToHex( (BYTE)sIn[ix] % 16);
|
||||||
}
|
}
|
||||||
sOut += (char *)buf;
|
sOut += (char *)buf;
|
||||||
}
|
}
|
||||||
@ -43,8 +43,8 @@ inline void URLDecode(const string &sIn, string& sOut) {
|
|||||||
for( size_t ix = 0; ix < sIn.size(); ix++ ) {
|
for( size_t ix = 0; ix < sIn.size(); ix++ ) {
|
||||||
BYTE ch = 0;
|
BYTE ch = 0;
|
||||||
if(sIn[ix]=='%') {
|
if(sIn[ix]=='%') {
|
||||||
ch = (fromHex(sIn[ix+1])<<4);
|
ch = (FromHex(sIn[ix+1])<<4);
|
||||||
ch |= fromHex(sIn[ix+2]);
|
ch |= FromHex(sIn[ix+2]);
|
||||||
ix += 2;
|
ix += 2;
|
||||||
} else if(sIn[ix] == '+') {
|
} else if(sIn[ix] == '+') {
|
||||||
ch = ' ';
|
ch = ' ';
|
||||||
@ -58,38 +58,38 @@ inline void URLDecode(const string &sIn, string& sOut) {
|
|||||||
class HttpReqInfo {
|
class HttpReqInfo {
|
||||||
public:
|
public:
|
||||||
HttpReqInfo() {
|
HttpReqInfo() {
|
||||||
_isHeaderFinished = false;
|
is_header_finished_ = false;
|
||||||
_isBodyFinished = false;
|
is_body_finished_ = false;
|
||||||
_contentLength = 0;
|
content_length_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseHeader(const string& buffer) {
|
bool ParseHeader(const string& buffer) {
|
||||||
return parseHeader(buffer.c_str(), buffer.size());
|
return ParseHeader(buffer.c_str(), buffer.size());
|
||||||
}
|
}
|
||||||
bool parseHeader(const char* buffer, size_t len) {
|
bool ParseHeader(const char* buffer, size_t len) {
|
||||||
string headerStr(buffer, len);
|
string headerStr(buffer, len);
|
||||||
size_t lpos = 0, rpos = 0;
|
size_t lpos = 0, rpos = 0;
|
||||||
vector<string> buf;
|
vector<string> buf;
|
||||||
rpos = headerStr.find("\n", lpos);
|
rpos = headerStr.find("\n", lpos);
|
||||||
if(string::npos == rpos) {
|
if(string::npos == rpos) {
|
||||||
LogError("headerStr[%s] illegal.", headerStr.c_str());
|
LOG(ERROR) << "headerStr[" << headerStr << "] illegal.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
string firstline(headerStr, lpos, rpos - lpos);
|
string firstline(headerStr, lpos, rpos - lpos);
|
||||||
trim(firstline);
|
Trim(firstline);
|
||||||
split(firstline, buf, " ");
|
Split(firstline, buf, " ");
|
||||||
if (3 != buf.size()) {
|
if (3 != buf.size()) {
|
||||||
LogError("parse header firstline[%s] failed.", firstline.c_str());
|
LOG(ERROR) << "parse header firstline [" << firstline << "] failed.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_headerMap[KEY_METHOD] = trim(buf[0]);
|
header_map_[KEY_METHOD] = Trim(buf[0]);
|
||||||
_headerMap[KEY_URI] = trim(buf[1]);
|
header_map_[KEY_URI] = Trim(buf[1]);
|
||||||
_headerMap[KEY_PROTOCOL] = trim(buf[2]);
|
header_map_[KEY_PROTOCOL] = Trim(buf[2]);
|
||||||
_parseUri(_headerMap[KEY_URI], _path, _methodGetMap);
|
ParseUri(header_map_[KEY_URI], path_, method_get_map_);
|
||||||
|
|
||||||
lpos = rpos + 1;
|
lpos = rpos + 1;
|
||||||
if(lpos >= headerStr.size()) {
|
if(lpos >= headerStr.size()) {
|
||||||
LogError("headerStr[%s] illegal.", headerStr.c_str());
|
LOG(ERROR) << "headerStr[" << headerStr << "] illegal.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//message header begin
|
//message header begin
|
||||||
@ -101,57 +101,57 @@ class HttpReqInfo {
|
|||||||
}
|
}
|
||||||
string k(s, 0, p);
|
string k(s, 0, p);
|
||||||
string v(s, p+1);
|
string v(s, p+1);
|
||||||
trim(k);
|
Trim(k);
|
||||||
trim(v);
|
Trim(v);
|
||||||
if(k.empty()||v.empty()) {
|
if(k.empty()||v.empty()) {
|
||||||
LogError("headerStr[%s] illegal.", headerStr.c_str());
|
LOG(ERROR) << "headerStr[" << headerStr << "] illegal.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
upper(k);
|
Upper(k);
|
||||||
_headerMap[k] = v;
|
header_map_[k] = v;
|
||||||
lpos = rpos + 1;
|
lpos = rpos + 1;
|
||||||
}
|
}
|
||||||
rpos ++;
|
rpos ++;
|
||||||
_isHeaderFinished = true;
|
is_header_finished_ = true;
|
||||||
string content_length;
|
string content_length;
|
||||||
if(!find("CONTENT-LENGTH", content_length)) {
|
if(!Find("CONTENT-LENGTH", content_length) || 0 == (content_length_ = atoi(content_length.c_str()))) {
|
||||||
_isBodyFinished = true;
|
is_body_finished_ = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
_contentLength = atoi(content_length.c_str());
|
content_length_ = atoi(content_length.c_str());
|
||||||
if(rpos < headerStr.size()) {
|
if(rpos < headerStr.size()) {
|
||||||
appendBody(headerStr.c_str() + rpos, headerStr.size() - rpos);
|
AppendBody(headerStr.c_str() + rpos, headerStr.size() - rpos);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
//message header end
|
//message header end
|
||||||
}
|
}
|
||||||
void appendBody(const char* buffer, size_t len) {
|
void AppendBody(const char* buffer, size_t len) {
|
||||||
if(_isBodyFinished) {
|
if(is_body_finished_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_body.append(buffer, len);
|
body_.append(buffer, len);
|
||||||
if(_body.size() >= _contentLength) {
|
if(body_.size() >= content_length_) {
|
||||||
_isBodyFinished = true;
|
is_body_finished_ = true;
|
||||||
} else {
|
} else {
|
||||||
_isBodyFinished = false;
|
is_body_finished_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool isHeaderFinished() const {
|
bool IsHeaderFinished() const {
|
||||||
return _isHeaderFinished;
|
return is_header_finished_;
|
||||||
}
|
}
|
||||||
bool isBodyFinished() const {
|
bool IsBodyFinished() const {
|
||||||
return _isBodyFinished;
|
return is_body_finished_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string& set(const string& key, const string& value) {
|
const string& Set(const string& key, const string& value) {
|
||||||
return _headerMap[key] = value;
|
return header_map_[key] = value;
|
||||||
}
|
}
|
||||||
bool find(const string& key, string& res)const {
|
bool Find(const string& key, string& res)const {
|
||||||
return _find(_headerMap, key, res);
|
return Find(header_map_, key, res);
|
||||||
}
|
}
|
||||||
bool GET(const string& argKey, string& res)const {
|
bool GET(const string& argKey, string& res)const {
|
||||||
string tmp;
|
string tmp;
|
||||||
if (!_find(_methodGetMap, argKey, tmp)) {
|
if (!Find(method_get_map_, argKey, tmp)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
URLDecode(tmp, res);
|
URLDecode(tmp, res);
|
||||||
@ -174,47 +174,44 @@ class HttpReqInfo {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//const string& getMethod() const
|
bool IsGET() const {
|
||||||
//{
|
|
||||||
// return _headerMap.find(KEY_METHOD)->second;
|
|
||||||
//}
|
|
||||||
bool isGET() const {
|
|
||||||
string str;
|
string str;
|
||||||
if(!_find(_headerMap, KEY_METHOD, str)) {
|
if(!Find(header_map_, KEY_METHOD, str)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return str == "GET";
|
return str == "GET";
|
||||||
}
|
}
|
||||||
bool isPOST() const {
|
bool IsPOST() const {
|
||||||
string str;
|
string str;
|
||||||
if(!_find(_headerMap, KEY_METHOD, str)) {
|
if(!Find(header_map_, KEY_METHOD, str)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return str == "POST";
|
return str == "POST";
|
||||||
}
|
}
|
||||||
const unordered_map<string, string> & getMethodGetMap() const {
|
const unordered_map<string, string> & GetMethodGetMap() const {
|
||||||
return _methodGetMap;
|
return method_get_map_;
|
||||||
}
|
}
|
||||||
const unordered_map<string, string> & getHeaders() const {
|
const unordered_map<string, string> & GetHeaders() const {
|
||||||
return _headerMap;
|
return header_map_;
|
||||||
}
|
}
|
||||||
const string& getBody() const {
|
const string& GetBody() const {
|
||||||
return _body;
|
return body_;
|
||||||
}
|
}
|
||||||
const string& getPath() const {
|
const string& GetPath() const {
|
||||||
return _path;
|
return path_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _isHeaderFinished;
|
bool is_header_finished_;
|
||||||
bool _isBodyFinished;
|
bool is_body_finished_;
|
||||||
size_t _contentLength;
|
size_t content_length_;
|
||||||
unordered_map<string, string> _headerMap;
|
unordered_map<string, string> header_map_;
|
||||||
unordered_map<string, string> _methodGetMap;
|
unordered_map<string, string> method_get_map_;
|
||||||
string _path;
|
string path_;
|
||||||
string _body;
|
string body_;
|
||||||
friend ostream& operator<<(ostream& os, const HttpReqInfo& obj);
|
friend ostream& operator<<(ostream& os, const HttpReqInfo& obj);
|
||||||
|
|
||||||
bool _find(const std::unordered_map<string, string>& mp, const string& key, string& res)const {
|
bool Find(const std::unordered_map<string, string>& mp, const string& key, string& res)const {
|
||||||
std::unordered_map<string, string>::const_iterator it = mp.find(key);
|
std::unordered_map<string, string>::const_iterator it = mp.find(key);
|
||||||
if(it == mp.end()) {
|
if(it == mp.end()) {
|
||||||
return false;
|
return false;
|
||||||
@ -223,7 +220,7 @@ class HttpReqInfo {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _parseUri(const string& uri, string& path, std::unordered_map<string, string>& mp) {
|
void ParseUri(const string& uri, string& path, std::unordered_map<string, string>& mp) {
|
||||||
if(uri.empty()) {
|
if(uri.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -259,7 +256,7 @@ class HttpReqInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator << (std::ostream& os, const husky::HttpReqInfo& obj) {
|
inline std::ostream& operator << (std::ostream& os, const husky::HttpReqInfo& obj) {
|
||||||
return os << obj._headerMap << obj._methodGetMap/* << obj._methodPostMap*/ << obj._path << obj._body ;
|
return os << obj.header_map_ << obj.method_get_map_/* << obj._methodPostMap*/ << obj.path_ << obj.body_ ;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef HUSKY_IREQUESTHANDLER_HPP
|
#ifndef HUSKY_IREQUESTHANDLER_HPP
|
||||||
#define HUSKY_IREQUESTHANDLER_HPP
|
#define HUSKY_IREQUESTHANDLER_HPP
|
||||||
|
|
||||||
#include "HttpReqInfo.hpp"
|
#include "http_req_info.h"
|
||||||
|
|
||||||
namespace husky {
|
namespace husky {
|
||||||
class IRequestHandler {
|
class IRequestHandler {
|
||||||
@ -9,8 +9,8 @@ class IRequestHandler {
|
|||||||
virtual ~IRequestHandler() {
|
virtual ~IRequestHandler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool doGET(const HttpReqInfo& httpReq, string& res) = 0;
|
virtual bool DoGET(const HttpReqInfo& httpReq, string& res) = 0;
|
||||||
virtual bool doPOST(const HttpReqInfo& httpReq, string& res) = 0;
|
virtual bool DoPOST(const HttpReqInfo& httpReq, string& res) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -16,34 +16,25 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "limonp/StdExtension.hpp"
|
#include "limonp/StdExtension.hpp"
|
||||||
#include "limonp/Logger.hpp"
|
#include "limonp/Logging.hpp"
|
||||||
|
|
||||||
namespace husky {
|
namespace husky {
|
||||||
static const size_t LISTEN_QUEUE_LEN = 1024;
|
static const size_t LISTEN_QUEUE_LEN = 1024;
|
||||||
|
|
||||||
typedef int SocketFd;
|
typedef int SocketFd;
|
||||||
inline SocketFd CreateAndListenSocket(int port) {
|
inline SocketFd CreateAndListenSocket(int port) {
|
||||||
SocketFd sock;
|
SocketFd sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
CHECK(sock != -1);
|
||||||
if (sock == -1) {
|
|
||||||
LogFatal("create socket failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
int optval = 1; // nozero
|
int optval = 1; // nozero
|
||||||
if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) {
|
CHECK(-1 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
|
||||||
LogFatal("setsockopt failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(port);
|
addr.sin_port = htons(port);
|
||||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
if (-1 == ::bind(sock, (sockaddr*)&addr, sizeof(addr))) {
|
CHECK(-1 != ::bind(sock, (sockaddr*)&addr, sizeof(addr)));
|
||||||
LogFatal(strerror(errno));
|
CHECK(-1 != ::listen(sock, LISTEN_QUEUE_LEN));
|
||||||
}
|
|
||||||
if (-1 == ::listen(sock, LISTEN_QUEUE_LEN)) {
|
|
||||||
LogFatal(strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
#ifndef HUSKY_THREADPOOLSERVER_H
|
#ifndef HUSKY_THREADPOOLSERVER_H
|
||||||
#define HUSKY_THREADPOOLSERVER_H
|
#define HUSKY_THREADPOOLSERVER_H
|
||||||
|
|
||||||
#include "NetUtils.hpp"
|
#include "net_util.h"
|
||||||
#include "WorkerThread.hpp"
|
#include "worker_thread.h"
|
||||||
|
|
||||||
namespace husky {
|
namespace husky {
|
||||||
using namespace limonp;
|
using namespace limonp;
|
||||||
@ -10,31 +10,31 @@ using namespace limonp;
|
|||||||
class ThreadPoolServer {
|
class ThreadPoolServer {
|
||||||
public:
|
public:
|
||||||
ThreadPoolServer(size_t thread_number, size_t queue_max_size, size_t port, IRequestHandler & handler):
|
ThreadPoolServer(size_t thread_number, size_t queue_max_size, size_t port, IRequestHandler & handler):
|
||||||
_pool(thread_number, queue_max_size), _reqHandler(handler), _host_socket(-1) {
|
pool_(thread_number, queue_max_size), req_handler_(handler), host_socket_(-1) {
|
||||||
_host_socket = CreateAndListenSocket(port);
|
host_socket_ = CreateAndListenSocket(port);
|
||||||
}
|
}
|
||||||
~ThreadPoolServer() {};
|
~ThreadPoolServer() {};
|
||||||
|
|
||||||
bool start() {
|
bool Start() {
|
||||||
_pool.start();
|
pool_.Start();
|
||||||
sockaddr_in clientaddr;
|
sockaddr_in clientaddr;
|
||||||
socklen_t nSize = sizeof(clientaddr);
|
socklen_t nSize = sizeof(clientaddr);
|
||||||
int clientSock;
|
int clientSock;
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
if(-1 == (clientSock = accept(_host_socket, (struct sockaddr*) &clientaddr, &nSize))) {
|
if(-1 == (clientSock = accept(host_socket_, (struct sockaddr*) &clientaddr, &nSize))) {
|
||||||
LogError(strerror(errno));
|
LOG(ERROR) << strerror(errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_pool.add(CreateTask<WorkerThread,int, IRequestHandler&>(clientSock, _reqHandler));
|
pool_.Add(CreateTask<WorkerThread,int, IRequestHandler&>(clientSock, req_handler_));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ThreadPool _pool;
|
ThreadPool pool_;
|
||||||
IRequestHandler & _reqHandler;
|
IRequestHandler & req_handler_;
|
||||||
int _host_socket;
|
int host_socket_;
|
||||||
}; // class ThreadPoolServer
|
}; // class ThreadPoolServer
|
||||||
} // namespace husky
|
} // namespace husky
|
||||||
|
|
105
server/husky/worker_thread.h
Normal file
105
server/husky/worker_thread.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#ifndef HUSKY_WORKER_HPP
|
||||||
|
#define HUSKY_WORKER_HPP
|
||||||
|
|
||||||
|
#include "limonp/ThreadPool.hpp"
|
||||||
|
#include "irequest_handler.h"
|
||||||
|
#include "net_util.h"
|
||||||
|
|
||||||
|
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};
|
||||||
|
|
||||||
|
class WorkerThread: public ITask {
|
||||||
|
public:
|
||||||
|
WorkerThread(int sockfs, IRequestHandler& reqHandler):
|
||||||
|
sockfd_(sockfs), req_handler_(reqHandler) {
|
||||||
|
}
|
||||||
|
virtual ~WorkerThread() {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Run() {
|
||||||
|
do {
|
||||||
|
if(!SetSockopt(sockfd_)) {
|
||||||
|
LOG(ERROR) << "_getsockopt failed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
string strSnd, strRetByHandler;
|
||||||
|
HttpReqInfo httpReq;
|
||||||
|
if(!Receive(sockfd_, httpReq)) {
|
||||||
|
LOG(ERROR) << "Receive failed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(httpReq.IsGET() && !req_handler_.DoGET(httpReq, strRetByHandler)) {
|
||||||
|
LOG(ERROR) << "DoGET failed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(httpReq.IsPOST() && !req_handler_.DoPOST(httpReq, strRetByHandler)) {
|
||||||
|
LOG(ERROR) << "DoPOST failed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strSnd = StringFormat(HTTP_FORMAT, CHARSET_UTF8, strRetByHandler.length(), strRetByHandler.c_str());
|
||||||
|
|
||||||
|
if(!Send(sockfd_, strSnd)) {
|
||||||
|
LOG(ERROR) << "Send failed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
|
||||||
|
if(-1 == close(sockfd_)) {
|
||||||
|
LOG(ERROR) << 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)) {
|
||||||
|
LOG(ERROR) << "ParseHeader failed. ";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
httpInfo.AppendBody(recvBuf, n);
|
||||||
|
}
|
||||||
|
if(n < 0) {
|
||||||
|
LOG(ERROR) << strerror(errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool Send(int sockfd, const string& strSnd) const {
|
||||||
|
if(-1 == send(sockfd, strSnd.c_str(), strSnd.length(), 0)) {
|
||||||
|
LOG(ERROR) << strerror(errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool SetSockopt(int sockfd) const {
|
||||||
|
if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char*)&LNG, sizeof(LNG))) {
|
||||||
|
LOG(ERROR) << strerror(errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) {
|
||||||
|
LOG(ERROR) << strerror(errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT))) {
|
||||||
|
LOG(ERROR) << strerror(errno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sockfd_;
|
||||||
|
IRequestHandler& req_handler_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -4,7 +4,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "limonp/Config.hpp"
|
#include "limonp/Config.hpp"
|
||||||
#include "husky/ThreadPoolServer.hpp"
|
#include "husky/thread_pool_server.h"
|
||||||
#include "Jieba.hpp"
|
#include "Jieba.hpp"
|
||||||
|
|
||||||
using namespace husky;
|
using namespace husky;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user