mirror of
https://github.com/yanyiwu/cppjieba.git
synced 2025-07-18 00:00:12 +08:00
update husky to be hpp
This commit is contained in:
parent
0ba5522b42
commit
5799d6d487
@ -1,8 +1,4 @@
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||
|
||||
SET(LIBHUSKY_SRC Daemon.cpp ServerFrame.cpp)
|
||||
ADD_LIBRARY(husky STATIC ${LIBHUSKY_SRC})
|
||||
|
||||
INSTALL(TARGETS husky ARCHIVE DESTINATION lib/CppJieba/Husky)
|
||||
INSTALL(FILES Daemon.h globals.h HttpReqInfo.hpp ServerFrame.h ThreadManager.hpp DESTINATION include/CppJieba/Husky)
|
||||
INSTALL(FILES HttpReqInfo.hpp ServerFrame.hpp ThreadManager.hpp DESTINATION include/CppJieba/Husky)
|
||||
|
@ -1,191 +0,0 @@
|
||||
#include "Daemon.h"
|
||||
|
||||
namespace Husky
|
||||
{
|
||||
|
||||
IWorkHandler * Daemon::m_pHandler;
|
||||
int Daemon::m_nChildPid = 0;
|
||||
const char* Daemon::m_pidFile = NULL;
|
||||
|
||||
bool Daemon::isAbnormalExit(int pid, int status)
|
||||
{
|
||||
bool bRestart = true;
|
||||
if (WIFEXITED(status)) //exit()or return
|
||||
{
|
||||
LogDebug("child normal termination, exit pid = %d, status = %d", pid, WEXITSTATUS(status));
|
||||
bRestart = false;
|
||||
}
|
||||
else if (WIFSIGNALED(status)) //signal方式退出
|
||||
{
|
||||
LogError("abnormal termination, pid = %d, signal number = %d%s", pid, WTERMSIG(status),
|
||||
#ifdef WCOREDUMP
|
||||
WCOREDUMP(status) ? " (core file generated)" :
|
||||
#endif
|
||||
"");
|
||||
|
||||
if (WTERMSIG(status) == SIGKILL)
|
||||
{
|
||||
bRestart = false;
|
||||
LogError("has been killed by user , exit pid = %d, status = %d", pid, WEXITSTATUS(status));
|
||||
}
|
||||
}
|
||||
else if (WIFSTOPPED(status)) //暂停的子进程退出
|
||||
{
|
||||
LogError("child stopped, pid = %d, signal number = %d", pid, WSTOPSIG(status));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("child other reason quit, pid = %d, signal number = %d", pid, WSTOPSIG(status));
|
||||
}
|
||||
return bRestart;
|
||||
}
|
||||
|
||||
bool Daemon::start()
|
||||
{
|
||||
string masterPidStr = loadFile2Str(m_pidFile);
|
||||
int masterPid = atoi(masterPidStr.c_str());
|
||||
if(masterPid)
|
||||
{
|
||||
if (kill(masterPid, 0) == 0)
|
||||
{
|
||||
LogError("Another instance exist, ready to quit!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
initAsDaemon();
|
||||
|
||||
char buf[64];
|
||||
sprintf(buf, "%d", getpid());
|
||||
if (!WriteStr2File(m_pidFile,buf ,"w"))
|
||||
{
|
||||
LogFatal("Write master pid fail!");
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
if (0 == pid)// child process do
|
||||
{
|
||||
signal(SIGUSR1, sigChildHandler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
|
||||
if(!m_pHandler->init())
|
||||
{
|
||||
LogFatal("m_pHandler init failed!");
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
LogDebug("Worker init ok pid = %d",(int)getpid());
|
||||
#endif
|
||||
|
||||
if (!m_pHandler->run())
|
||||
{
|
||||
LogError("m_pHandler run finish with failure!");
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
LogDebug("run finish -ok!");
|
||||
#endif
|
||||
|
||||
//if(!m_pHandler->dispose())
|
||||
//{
|
||||
// LogError("m_pHandler dispose with failure!");
|
||||
// return false;
|
||||
//}
|
||||
#ifdef DEBUG
|
||||
//LogDebug("Worker dispose -ok!");
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
m_nChildPid=pid;
|
||||
int status;
|
||||
pid = wait(&status);
|
||||
if (!isAbnormalExit(pid, status))
|
||||
{
|
||||
LogDebug("child exit normally! and Daemon exit");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Daemon::stop()
|
||||
{
|
||||
string masterPidStr = loadFile2Str(m_pidFile);
|
||||
int masterPid = atoi(masterPidStr.c_str());
|
||||
if(masterPid)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
LogDebug("read last masterPid[%d]",masterPid);
|
||||
#endif
|
||||
if (kill(masterPid, 0) == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
LogDebug("find previous daemon pid= %d, current pid= %d", masterPid, getpid());
|
||||
#endif
|
||||
kill(masterPid, SIGTERM);
|
||||
|
||||
int tryTime = 200;
|
||||
while (kill(masterPid, 0) == 0 && --tryTime)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
if (!tryTime && kill(masterPid, 0) == 0)
|
||||
{
|
||||
LogError("Time out shutdown fail!");
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo("previous daemon pid[%d] shutdown ok.", masterPid);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
LogError("Another instance doesn't exist, ready to quit!");
|
||||
return false;
|
||||
}
|
||||
|
||||
void Daemon::initAsDaemon()
|
||||
{
|
||||
if (fork() > 0)
|
||||
exit(0);
|
||||
setsid();
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
signal(SIGTERM, sigMasterHandler);
|
||||
signal(SIGINT, sigMasterHandler);
|
||||
signal(SIGQUIT, sigMasterHandler);
|
||||
signal(SIGKILL, sigMasterHandler);
|
||||
}
|
||||
|
||||
void Daemon::sigMasterHandler(int sig)
|
||||
{
|
||||
kill(m_nChildPid,SIGUSR1);
|
||||
LogDebug("master = %d sig child =%d!",getpid(),m_nChildPid);
|
||||
|
||||
}
|
||||
|
||||
void Daemon::sigChildHandler(int sig)
|
||||
{
|
||||
if (sig == SIGUSR1)
|
||||
{
|
||||
m_pHandler->dispose();
|
||||
LogDebug("master = %d signal accept current pid =%d!",getppid(),getpid());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
#ifndef HUSKY_DAEMON_H_
|
||||
#define HUSKY_DAEMON_H_
|
||||
#include "globals.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include "../Limonp/logger.hpp"
|
||||
|
||||
namespace Husky
|
||||
{
|
||||
using namespace Limonp;
|
||||
|
||||
class IWorkHandler
|
||||
{
|
||||
public:
|
||||
virtual ~IWorkHandler(){}
|
||||
virtual bool init() = 0;
|
||||
virtual bool dispose() = 0;
|
||||
virtual bool run() = 0;
|
||||
};
|
||||
|
||||
class Daemon
|
||||
{
|
||||
public:
|
||||
Daemon(IWorkHandler * workHandler, const char* pidFile)
|
||||
{
|
||||
m_pHandler = workHandler;
|
||||
m_pidFile = pidFile;
|
||||
}
|
||||
~Daemon(){};
|
||||
public:
|
||||
bool start();
|
||||
bool stop();
|
||||
public:
|
||||
static void initAsDaemon();
|
||||
static void sigMasterHandler(int sig);
|
||||
static void sigChildHandler(int sig);
|
||||
static bool isAbnormalExit(int pid, int status);
|
||||
private:
|
||||
//static IRequestHandler* m_pHandler;
|
||||
//static ServerFrame m_ServerFrame;
|
||||
static int m_nChildPid;
|
||||
static IWorkHandler * m_pHandler;
|
||||
static const char* m_pidFile;
|
||||
};
|
||||
}
|
||||
#endif
|
@ -3,9 +3,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "../Limonp/logger.hpp"
|
||||
#include "../Limonp/str_functs.hpp"
|
||||
#include "globals.h"
|
||||
#include "Limonp/logger.hpp"
|
||||
|
||||
namespace Husky
|
||||
{
|
||||
|
@ -1,231 +0,0 @@
|
||||
#include "ServerFrame.h"
|
||||
namespace Husky
|
||||
{
|
||||
const struct timeval ServerFrame::m_timev = {SOCKET_TIMEOUT, 0};
|
||||
|
||||
pthread_mutex_t ServerFrame::m_pmAccept;
|
||||
bool ServerFrame::m_bShutdown = false;
|
||||
|
||||
bool ServerFrame::dispose()
|
||||
{
|
||||
m_bShutdown=true;
|
||||
if (SOCKET_ERROR==closesocket(m_lsnSock))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int sockfd;
|
||||
struct sockaddr_in dest;
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
bzero(&dest, sizeof(dest));
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htons(m_nLsnPort);
|
||||
if (inet_aton("127.0.0.1", (struct in_addr *) &dest.sin_addr.s_addr) == 0)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) < 0)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
close(sockfd);
|
||||
if(!m_pHandler->dispose())
|
||||
{
|
||||
LogFatal("m_pHandler dispose failed.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServerFrame::run()
|
||||
{
|
||||
if(SOCKET_ERROR==listen(m_lsnSock,LISEN_QUEUR_LEN))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
ThreadManager thrMngr;
|
||||
int i;
|
||||
SPara para;
|
||||
para.hSock=m_lsnSock;
|
||||
para.pHandler=m_pHandler;
|
||||
for (i=0;i<m_nThreadCount;i++)
|
||||
{
|
||||
if (0!=thrMngr.CreateThread(ServerThread, ¶))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogDebug("expect thread count %d, real count %d",m_nThreadCount,i);
|
||||
if(i==0)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo("server start to run.........");
|
||||
|
||||
if (thrMngr.WaitMultipleThread()!=0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void* ServerFrame::ServerThread(void *lpParameter )
|
||||
{
|
||||
SPara *pPara=(SPara*)lpParameter;
|
||||
SOCKET hSockLsn=pPara->hSock;
|
||||
IRequestHandler *pHandler=pPara->pHandler;
|
||||
int nRetCode;
|
||||
linger lng;
|
||||
char chRecvBuf[RECV_BUFFER];
|
||||
|
||||
SOCKET hClientSock;
|
||||
string strHttpResp;
|
||||
|
||||
sockaddr_in clientaddr;
|
||||
socklen_t nSize = sizeof(clientaddr);
|
||||
while(!m_bShutdown)
|
||||
{
|
||||
HttpReqInfo httpReq;
|
||||
pthread_mutex_lock(&m_pmAccept);
|
||||
hClientSock=accept(hSockLsn,(sockaddr *)&clientaddr, &nSize);
|
||||
pthread_mutex_unlock(&m_pmAccept);
|
||||
|
||||
if(hClientSock==SOCKET_ERROR)
|
||||
{
|
||||
if(!m_bShutdown)
|
||||
LogError("error [%s]", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
httpReq[CLIENT_IP_K] = inet_ntoa(clientaddr.sin_addr);// inet_ntoa is not thread safety at some version
|
||||
|
||||
lng.l_linger=1;
|
||||
lng.l_onoff=1;
|
||||
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_LINGER,(char*)&lng,sizeof(lng)))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_RCVTIMEO,(char*)&m_timev,sizeof(m_timev)))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_SNDTIMEO,(char*)&m_timev,sizeof(m_timev)))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
string strRec;
|
||||
string strSnd;
|
||||
memset(chRecvBuf,0,sizeof(chRecvBuf));
|
||||
nRetCode = recv(hClientSock, chRecvBuf, RECV_BUFFER, 0);
|
||||
strRec = chRecvBuf;
|
||||
|
||||
#ifdef HUKSY_DEBUG
|
||||
LogDebug("request[%s]", strRec.c_str());
|
||||
#endif
|
||||
|
||||
if(SOCKET_ERROR==nRetCode)
|
||||
{
|
||||
LogDebug("error [%s]", strerror(errno));
|
||||
closesocket(hClientSock);
|
||||
continue;
|
||||
}
|
||||
if(0==nRetCode)
|
||||
{
|
||||
LogDebug("connection has been gracefully closed");
|
||||
closesocket(hClientSock);
|
||||
continue;
|
||||
}
|
||||
httpReq.load(strRec);
|
||||
|
||||
pHandler->do_GET(httpReq, strSnd);
|
||||
|
||||
char chHttpHeader[2048];
|
||||
|
||||
sprintf(chHttpHeader, RESPONSE_FORMAT, RESPONSE_CHARSET_UTF8, int(strSnd.length()));
|
||||
|
||||
strHttpResp=chHttpHeader;
|
||||
strHttpResp+=strSnd;
|
||||
#ifdef HUKSY_DEBUG
|
||||
LogDebug("response'body [%s]", strSnd.c_str());
|
||||
#endif
|
||||
|
||||
if (SOCKET_ERROR==send(hClientSock,strHttpResp.c_str(),strHttpResp.length(),0))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
closesocket(hClientSock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
bool ServerFrame::init()
|
||||
{
|
||||
|
||||
if (!BindToLocalHost(m_lsnSock,m_nLsnPort))
|
||||
{
|
||||
LogFatal("BindToLocalHost failed.");
|
||||
return false;
|
||||
}
|
||||
LogInfo("init ok {port:%d, threadNum:%d}", m_nLsnPort, m_nThreadCount);
|
||||
|
||||
if(!m_pHandler->init())
|
||||
{
|
||||
LogFatal("m_pHandler init failed.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServerFrame::BindToLocalHost(SOCKET &sock,u_short nPort)
|
||||
{
|
||||
sock=socket(AF_INET,SOCK_STREAM,0);
|
||||
if(INVALID_SOCKET==sock)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
int nRet = 1;
|
||||
if(SOCKET_ERROR==setsockopt(m_lsnSock, SOL_SOCKET, SO_REUSEADDR, (char*)&nRet, sizeof(nRet)))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
struct sockaddr_in addrSock;
|
||||
addrSock.sin_family=AF_INET;
|
||||
addrSock.sin_port=htons(nPort);
|
||||
addrSock.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
int retval;
|
||||
retval = ::bind(sock,(sockaddr*)&addrSock,sizeof(sockaddr));
|
||||
if(SOCKET_ERROR==retval)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
closesocket(sock);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
#ifndef HUSKY_SERVERFRAME_H
|
||||
#define HUSKY_SERVERFRAME_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include "globals.h"
|
||||
#include "ThreadManager.hpp"
|
||||
#include "HttpReqInfo.hpp"
|
||||
#include "Daemon.h"
|
||||
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define closesocket close
|
||||
#define RECV_BUFFER 10240
|
||||
#define LISEN_QUEUR_LEN 1024
|
||||
|
||||
|
||||
namespace Husky
|
||||
{
|
||||
using namespace Limonp;
|
||||
typedef int SOCKET;
|
||||
|
||||
class IRequestHandler
|
||||
{
|
||||
public:
|
||||
virtual ~IRequestHandler(){};
|
||||
public:
|
||||
virtual bool init() = 0;
|
||||
virtual bool dispose() = 0;
|
||||
|
||||
virtual bool do_GET(const HttpReqInfo& httpReq, string& res) = 0;
|
||||
|
||||
};
|
||||
|
||||
struct SPara
|
||||
{
|
||||
SOCKET hSock;
|
||||
IRequestHandler * pHandler;
|
||||
};
|
||||
|
||||
class ServerFrame: public IWorkHandler
|
||||
{
|
||||
public:
|
||||
ServerFrame(unsigned nPort, unsigned nThreadCount, IRequestHandler* pHandler)
|
||||
{
|
||||
m_nLsnPort = nPort;
|
||||
m_nThreadCount = nThreadCount;
|
||||
m_pHandler = pHandler;
|
||||
pthread_mutex_init(&m_pmAccept,NULL);
|
||||
};
|
||||
virtual ~ServerFrame(){pthread_mutex_destroy(&m_pmAccept);};
|
||||
virtual bool init();
|
||||
virtual bool dispose();
|
||||
virtual bool run();
|
||||
|
||||
protected:
|
||||
|
||||
bool BindToLocalHost(SOCKET &sock,u_short nPort);
|
||||
|
||||
static void * ServerThread(void * lpParameter );
|
||||
|
||||
private:
|
||||
u_short m_nLsnPort;
|
||||
u_short m_nThreadCount;
|
||||
SOCKET m_lsnSock;
|
||||
IRequestHandler *m_pHandler;
|
||||
static bool m_bShutdown;
|
||||
static pthread_mutex_t m_pmAccept;
|
||||
static const struct timeval m_timev;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif
|
313
src/Husky/ServerFrame.hpp
Normal file
313
src/Husky/ServerFrame.hpp
Normal file
@ -0,0 +1,313 @@
|
||||
#ifndef HUSKY_SERVERFRAME_H
|
||||
#define HUSKY_SERVERFRAME_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include "ThreadManager.hpp"
|
||||
#include "HttpReqInfo.hpp"
|
||||
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define closesocket close
|
||||
#define RECV_BUFFER 10240
|
||||
#define LISEN_QUEUR_LEN 1024
|
||||
|
||||
|
||||
namespace Husky
|
||||
{
|
||||
using namespace Limonp;
|
||||
typedef int SOCKET;
|
||||
const struct timeval SOCKET_TIMEOUT = {2, 0};
|
||||
const char* const RESPONSE_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: FrameServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n";
|
||||
const char* const RESPONSE_CHARSET_UTF8 = "UTF-8";
|
||||
const char* const RESPONSE_CHARSET_GB2312 = "GB2312";
|
||||
const char* const CLIENT_IP_K = "CLIENT_IP";
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned int u_int;
|
||||
|
||||
class IRequestHandler
|
||||
{
|
||||
public:
|
||||
virtual ~IRequestHandler(){};
|
||||
public:
|
||||
virtual bool init() = 0;
|
||||
virtual bool dispose() = 0;
|
||||
|
||||
virtual bool do_GET(const HttpReqInfo& httpReq, string& res) = 0;
|
||||
|
||||
};
|
||||
|
||||
struct SPara
|
||||
{
|
||||
SOCKET hSock;
|
||||
IRequestHandler * pHandler;
|
||||
pthread_mutex_t * ppmAccept;
|
||||
bool * pShutdown;
|
||||
};
|
||||
|
||||
class ServerFrame//: public IWorkHandler
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t m_pmAccept;
|
||||
bool m_bShutdown;
|
||||
public:
|
||||
ServerFrame(unsigned nPort, unsigned nThreadCount, IRequestHandler* pHandler)
|
||||
{
|
||||
m_nLsnPort = nPort;
|
||||
m_nThreadCount = nThreadCount;
|
||||
m_pHandler = pHandler;
|
||||
m_bShutdown = false;
|
||||
pthread_mutex_init(&m_pmAccept,NULL);
|
||||
};
|
||||
virtual ~ServerFrame(){pthread_mutex_destroy(&m_pmAccept);};
|
||||
virtual bool init()
|
||||
{
|
||||
|
||||
if (!BindToLocalHost(m_lsnSock,m_nLsnPort))
|
||||
{
|
||||
LogFatal("BindToLocalHost failed.");
|
||||
return false;
|
||||
}
|
||||
LogInfo("init ok {port:%d, threadNum:%d}", m_nLsnPort, m_nThreadCount);
|
||||
|
||||
if(!m_pHandler->init())
|
||||
{
|
||||
LogFatal("m_pHandler init failed.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool dispose()
|
||||
{
|
||||
m_bShutdown=true;
|
||||
if (SOCKET_ERROR==closesocket(m_lsnSock))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int sockfd;
|
||||
struct sockaddr_in dest;
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
bzero(&dest, sizeof(dest));
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htons(m_nLsnPort);
|
||||
if (inet_aton("127.0.0.1", (struct in_addr *) &dest.sin_addr.s_addr) == 0)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) < 0)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
close(sockfd);
|
||||
if(!m_pHandler->dispose())
|
||||
{
|
||||
LogFatal("m_pHandler dispose failed.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool run()
|
||||
{
|
||||
if(SOCKET_ERROR==listen(m_lsnSock,LISEN_QUEUR_LEN))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
ThreadManager thrMngr;
|
||||
int i;
|
||||
SPara para;
|
||||
para.hSock=m_lsnSock;
|
||||
para.pHandler=m_pHandler;
|
||||
para.ppmAccept=&m_pmAccept;
|
||||
para.pShutdown=&m_bShutdown;
|
||||
for (i=0;i<m_nThreadCount;i++)
|
||||
{
|
||||
if (0!=thrMngr.CreateThread(ServerThread, ¶))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogDebug("expect thread count %d, real count %d",m_nThreadCount,i);
|
||||
if(i==0)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo("server start to run.........");
|
||||
|
||||
if (thrMngr.WaitMultipleThread()!=0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool BindToLocalHost(SOCKET &sock,u_short nPort)
|
||||
{
|
||||
sock=socket(AF_INET,SOCK_STREAM,0);
|
||||
if(INVALID_SOCKET==sock)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
int nRet = 1;
|
||||
if(SOCKET_ERROR==setsockopt(m_lsnSock, SOL_SOCKET, SO_REUSEADDR, (char*)&nRet, sizeof(nRet)))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
struct sockaddr_in addrSock;
|
||||
addrSock.sin_family=AF_INET;
|
||||
addrSock.sin_port=htons(nPort);
|
||||
addrSock.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
int retval;
|
||||
retval = ::bind(sock,(sockaddr*)&addrSock,sizeof(sockaddr));
|
||||
if(SOCKET_ERROR==retval)
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
closesocket(sock);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static void * ServerThread(void * lpParameter )
|
||||
{
|
||||
SPara *pPara=(SPara*)lpParameter;
|
||||
SOCKET hSockLsn=pPara->hSock;
|
||||
IRequestHandler *pHandler=pPara->pHandler;
|
||||
bool* pShutdown = pPara->pShutdown;
|
||||
pthread_mutex_t* ppmAccept = pPara->ppmAccept;
|
||||
|
||||
int nRetCode;
|
||||
linger lng;
|
||||
char chRecvBuf[RECV_BUFFER];
|
||||
|
||||
SOCKET hClientSock;
|
||||
string strHttpResp;
|
||||
|
||||
sockaddr_in clientaddr;
|
||||
socklen_t nSize = sizeof(clientaddr);
|
||||
while(!(*pShutdown))
|
||||
{
|
||||
HttpReqInfo httpReq;
|
||||
pthread_mutex_lock(ppmAccept);
|
||||
hClientSock=accept(hSockLsn,(sockaddr *)&clientaddr, &nSize);
|
||||
pthread_mutex_unlock(ppmAccept);
|
||||
|
||||
if(hClientSock==SOCKET_ERROR)
|
||||
{
|
||||
if(!(*pShutdown))
|
||||
LogError("error [%s]", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
httpReq[CLIENT_IP_K] = inet_ntoa(clientaddr.sin_addr);// inet_ntoa is not thread safety at some version
|
||||
|
||||
lng.l_linger=1;
|
||||
lng.l_onoff=1;
|
||||
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_LINGER,(char*)&lng,sizeof(lng)))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_RCVTIMEO,(char*)&SOCKET_TIMEOUT,sizeof(SOCKET_TIMEOUT)))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
if(SOCKET_ERROR==setsockopt(hClientSock,SOL_SOCKET,SO_SNDTIMEO,(char*)&SOCKET_TIMEOUT,sizeof(SOCKET_TIMEOUT)))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
string strRec;
|
||||
string strSnd;
|
||||
memset(chRecvBuf,0,sizeof(chRecvBuf));
|
||||
nRetCode = recv(hClientSock, chRecvBuf, RECV_BUFFER, 0);
|
||||
strRec = chRecvBuf;
|
||||
|
||||
#ifdef HUKSY_DEBUG
|
||||
LogDebug("request[%s]", strRec.c_str());
|
||||
#endif
|
||||
|
||||
if(SOCKET_ERROR==nRetCode)
|
||||
{
|
||||
LogDebug("error [%s]", strerror(errno));
|
||||
closesocket(hClientSock);
|
||||
continue;
|
||||
}
|
||||
if(0==nRetCode)
|
||||
{
|
||||
LogDebug("connection has been gracefully closed");
|
||||
closesocket(hClientSock);
|
||||
continue;
|
||||
}
|
||||
httpReq.load(strRec);
|
||||
|
||||
pHandler->do_GET(httpReq, strSnd);
|
||||
|
||||
char chHttpHeader[2048];
|
||||
|
||||
sprintf(chHttpHeader, RESPONSE_FORMAT, RESPONSE_CHARSET_UTF8, int(strSnd.length()));
|
||||
|
||||
strHttpResp=chHttpHeader;
|
||||
strHttpResp+=strSnd;
|
||||
#ifdef HUKSY_DEBUG
|
||||
LogDebug("response'body [%s]", strSnd.c_str());
|
||||
#endif
|
||||
|
||||
if (SOCKET_ERROR==send(hClientSock,strHttpResp.c_str(),strHttpResp.length(),0))
|
||||
{
|
||||
LogError("error [%s]", strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
closesocket(hClientSock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
u_short m_nLsnPort;
|
||||
u_short m_nThreadCount;
|
||||
SOCKET m_lsnSock;
|
||||
IRequestHandler *m_pHandler;
|
||||
//static bool m_bShutdown;
|
||||
//static pthread_mutex_t m_pmAccept;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif
|
@ -1,24 +0,0 @@
|
||||
#ifndef HUSKY_GLOBALS_H
|
||||
#define HUSKY_GLOBALS_H
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
namespace Husky
|
||||
{
|
||||
|
||||
const char* const RESPONSE_CHARSET_UTF8 = "UTF-8";
|
||||
const char* const RESPONSE_CHARSET_GB2312 = "GB2312";
|
||||
const char* const CLIENT_IP_K = "CLIENT_IP";
|
||||
|
||||
const unsigned int SOCKET_TIMEOUT = 2;
|
||||
|
||||
const char* const RESPONSE_FORMAT = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: FrameServer/1.0.0\r\nContent-Type: text/json; charset=%s\r\nContent-Length: %d\r\n\r\n";
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned int u_int;
|
||||
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user