diff --git a/demo/Makefile b/demo/Makefile index 4615465..a305a01 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -2,7 +2,6 @@ CXX := g++ LD := g++ AR := ar rc -INCS := -I../limonp DEBUG_CXXFLAGS := -g -Wall -DDEBUG RELEASE_CXXFLAGS := -Wall -O3 @@ -15,7 +14,9 @@ else LDFLAGS := ${RELEASE_LDFLAGS} endif -DOLINK := $(LD) $(LDFLAGS) +INCS := -I../limonp +LINK := -lpthread + SOURCES := $(wildcard *.cpp) OBJS := $(patsubst %.cpp,%.o,$(SOURCES)) DEMOS := $(patsubst %.cpp,%.demo,$(SOURCES)) @@ -23,19 +24,26 @@ DEMOS := $(patsubst %.cpp,%.demo,$(SOURCES)) CPPJIEBADIR := ../cppjieba LIBCPPJIEBA := $(CPPJIEBADIR)/libcppjieba.a +HUSKYDIR := ../husky +LIBHUSKYA := $(HUSKYDIR)/libhusky.a + .PHONY: clean $(LIBCPPJIEBA) all: $(DEMOS) -%.demo: %.cpp $(LIBCPPJIEBA) - $(CXX) -o $@ $(CXXFLAGS) $^ $(INCS) +%.demo: %.cpp $(LIBCPPJIEBA) $(LIBHUSKYA) + $(CXX) -o $@ $(CXXFLAGS) $^ $(INCS) $(LINK) $(LIBCPPJIEBA): cd $(CPPJIEBADIR) && $(MAKE) +$(LIBHUSKYA): + cd $(HUSKYDIR) && $(MAKE) + clean: rm -f *.o *.ut *.d *.d.* $(DEMOS) cd $(CPPJIEBADIR) && make clean + cd $(HUSKYDIR) && make clean sinclude $(SOURCES:.cpp=.d) %.d:%.cpp diff --git a/demo/restart.sh b/demo/restart.sh new file mode 100755 index 0000000..0bebf67 --- /dev/null +++ b/demo/restart.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +sh start.sh +sh stop.sh diff --git a/demo/server.cpp b/demo/server.cpp new file mode 100644 index 0000000..7dc0285 --- /dev/null +++ b/demo/server.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include "../husky/Daemon.h" +#include "../husky/ServerFrame.h" +#include "../cppjieba/MPSegment.h" +#include "../cppjieba/HMMSegment.h" +#include "../cppjieba/MixSegment.h" + +using namespace Husky; +using namespace CppJieba; + +const char * const DEFAULT_DICTPATH = "../dicts/jieba.dict.utf8"; +const char * const DEFAULT_MODELPATH = "../dicts/hmm_model.utf8"; + +class ServerDemo: public IRequestHandler +{ + public: + ServerDemo(){}; + virtual ~ServerDemo(){}; + virtual bool init(){return _segment.init(DEFAULT_DICTPATH, DEFAULT_MODELPATH);}; + virtual bool dispose(){return _segment.dispose();}; + public: + virtual bool do_GET(const HttpReqInfo& httpReq, string& strSnd) + { + //HttpReqInfo info = httpReq; + strSnd = httpReq.toString(); + return true; + } + private: + MixSegment _segment; +}; + +int main(int argc,char* argv[]) +{ + if(argc != 7) + { + printf("usage: %s -n THREAD_NUMBER -p LISTEN_PORT -k start|stop\n",argv[0]); + return -1; + } + ArgvContext arg(argc, argv); + unsigned int port = atoi(arg["-p"].c_str()); + unsigned int threadNum = atoi(arg["-n"].c_str()); + + ServerDemo s; + Daemon daemon(&s); + if(arg["-k"] == "start") + { + return !daemon.Start(port, threadNum); + } + else + { + return !daemon.Stop(); + } +} + diff --git a/demo/start.sh b/demo/start.sh new file mode 100755 index 0000000..5882c46 --- /dev/null +++ b/demo/start.sh @@ -0,0 +1,2 @@ +#!/bin/sh +./server.demo -n 4 -p 11258 -k start >> run.log 2>&1 & diff --git a/demo/stop.sh b/demo/stop.sh new file mode 100755 index 0000000..ec4f59a --- /dev/null +++ b/demo/stop.sh @@ -0,0 +1,2 @@ +#!/bin/sh +./server.demo -n 4 -p 11258 -k stop diff --git a/husky/Daemon.cpp b/husky/Daemon.cpp new file mode 100644 index 0000000..d226a66 --- /dev/null +++ b/husky/Daemon.cpp @@ -0,0 +1,196 @@ +#include "Daemon.h" + +namespace Husky +{ + + IRequestHandler * Daemon::m_pHandler; + ServerFrame Daemon::m_ServerFrame; + int Daemon::m_nChildPid = 0; + + 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(unsigned int port, unsigned int threadNum) + { + string masterPidStr = loadFile2Str(MASTER_PID_FILE); + 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(MASTER_PID_FILE,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; + } + if (!m_ServerFrame.CreateServer(port, threadNum, m_pHandler)) + { + LogFatal("m_ServerFrame CreateServer(%d, %d, m_pHandler) fail!", port, threadNum); + return false; + } +#ifdef DEBUG + LogDebug("Worker init ok pid = %d",(int)getpid()); +#endif + + if (!m_ServerFrame.RunServer()) + { + LogError("m_ServerFrame.RunServer finish -fail!"); + return false; + } +#ifdef DEBUG + LogDebug("run finish -ok!"); +#endif + + if(!m_pHandler->dispose()) + { + LogError("m_pHandler.dispose -fail!"); + 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(MASTER_PID_FILE); + 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_ServerFrame.CloseServer(); + LogDebug("master = %d signal accept current pid =%d!",getppid(),getpid()); + } + + } + +} + + diff --git a/husky/Daemon.h b/husky/Daemon.h new file mode 100644 index 0000000..532765a --- /dev/null +++ b/husky/Daemon.h @@ -0,0 +1,40 @@ +#ifndef HUSKY_DAEMON_H_ +#define HUSKY_DAEMON_H_ +#include "globals.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "ServerFrame.h" + +namespace Husky +{ + using namespace Limonp; + + class Daemon + { + public: + Daemon(IRequestHandler * pHandler) + { + m_pHandler = pHandler; + } + ~Daemon(){}; + public: + bool Start(unsigned int port, unsigned int threadNum); + 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; + }; +} +#endif diff --git a/husky/HttpReqInfo.hpp b/husky/HttpReqInfo.hpp new file mode 100644 index 0000000..97e537a --- /dev/null +++ b/husky/HttpReqInfo.hpp @@ -0,0 +1,172 @@ +#ifndef HUSKY_HTTP_REQINFO_H +#define HUSKY_HTTP_REQINFO_H + +#include +#include +#include "globals.h" +#include +#include +#include + +namespace Husky +{ + using namespace Limonp; + + static const char* const KEY_METHOD = "METHOD"; + static const char* const KEY_PATH = "PATH"; + static const char* const KEY_PROTOCOL = "PROTOCOL"; + + class HttpReqInfo + { + public: + bool load(const string& headerStr) + { + size_t lpos = 0, rpos = 0; + vector buf; + rpos = headerStr.find("\n", lpos); + if(string::npos == rpos) + { + LogFatal("headerStr illegal."); + return false; + } + string firstline(headerStr, lpos, rpos - lpos); + trim(firstline); + if(!splitStr(firstline, buf, " ") || 3 != buf.size()) + { + LogFatal("parse header first line failed."); + 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()) + { + LogFatal("headerStr illegal"); + 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()) + { + LogFatal("headerStr illegal."); + return false; + } + _headerMap[upperStr(k)] = v; + lpos = rpos + 1; + } + //message header end + + //body begin + + return true; + } + public: + string& operator[] (const string& key) + { + return _headerMap[key]; + } + 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); + } + bool POST(const string& argKey, string& res)const + { + return _find(_methodPostMap, argKey, res); + } + private: + HashMap _headerMap; + HashMap _methodGetMap; + HashMap _methodPostMap; + private: + bool _find(const HashMap& mp, const string& key, string& res)const + { + HashMap::const_iterator it = mp.find(key); + if(it == mp.end()) + { + return false; + } + res = it->second; + return true; + } + public: + //string toString() const;// function for debug because of heavy time consuming + string toString() const + { + string res("{"); + res += HashMapToString(_headerMap); + res += ","; + res += HashMapToString(_methodGetMap); + res += ","; + res += HashMapToString(_methodPostMap); + res += "}"; + return res; + } + private: + bool _parseUrl(const string& url, HashMap& mp) + { + if(url.empty()) + { + return false; + } + + uint pos = url.find('?'); + if(string::npos == pos) + { + return false; + } + uint kleft = 0, kright = 0; + uint vleft = 0, vright = 0; + for(uint 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; + } + }; + +} + +#endif diff --git a/husky/Makefile b/husky/Makefile new file mode 100644 index 0000000..84395f8 --- /dev/null +++ b/husky/Makefile @@ -0,0 +1,42 @@ +CXX := g++ +LD := g++ +AR := ar rc + +DEBUG_CXXFLAGS := -g -Wall -DDEBUG +RELEASE_CXXFLAGS := -Wall -O3 + +ifeq (YES, ${RELEASE}) + CXXFLAGS := ${RELEASE_CXXFLAGS} + LDFLAGS := ${RELEASE_LDFLAGS} +else + CXXFLAGS := ${DEBUG_CXXFLAGS} + LDFLAGS := ${DEBUG_LDFLAGS} +endif + +DOLINK := $(LD) $(LDFLAGS) -o $@ $^ +DOPACK := $(AR) +SOURCES = $(wildcard *.cpp) +OBJS := $(patsubst %.cpp,%.o,$(SOURCES)) + +INC := -I../limonp +LIBA := libhusky.a + +.PHONY: clean + +all: $(LIBA) + +%.o: %.cpp + $(CXX) -c $(CXXFLAGS) $< $(INC) + +${LIBA}: $(OBJS) + $(DOPACK) $@ $(OBJS) + +clean: + rm -f *.o *.d *.d.* $(LIBA) + +sinclude $(SOURCES:.cpp=.d) +%.d:%.cpp + @set -e; rm -f $@; \ + $(CXX) -MM $< > $@.$$$$; \ + sed 's,\($*\).o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ diff --git a/husky/ServerFrame.cpp b/husky/ServerFrame.cpp new file mode 100644 index 0000000..9903fb7 --- /dev/null +++ b/husky/ServerFrame.cpp @@ -0,0 +1,227 @@ +#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::CloseServer() + { + 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); + LogInfo("CloseServer ok."); + return true; + + } + + bool ServerFrame::RunServer() + { + 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;ihSock; + 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 DEBUG + LogDebug("response[%s]", strRec.c_str()); +#endif + + if(SOCKET_ERROR==nRetCode) + { + LogError("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, strSnd.length()); + + strHttpResp=chHttpHeader; + strHttpResp+=strSnd; + + if (SOCKET_ERROR==send(hClientSock,strHttpResp.c_str(),strHttpResp.length(),0)) + { + LogError("error [%s]", strerror(errno)); + } + +#ifdef DEBUG + LogDebug("send response [%s] ", strHttpResp.c_str()); +#endif + + closesocket(hClientSock); + } + + return 0; + + } + + bool ServerFrame::CreateServer(u_short nPort,u_short nThreadCount,IRequestHandler *pHandler) + { + m_nLsnPort=nPort; + m_nThreadCount=nThreadCount; + m_pHandler=pHandler; + + if (!BindToLocalHost(m_lsnSock,m_nLsnPort)) + { + return false; + } + pthread_mutex_init(&m_pmAccept,NULL); + LogInfo("CreatServer ok {port:%d, threadNum:%d}", nPort, nThreadCount); + 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; + + } +} diff --git a/husky/ServerFrame.h b/husky/ServerFrame.h new file mode 100644 index 0000000..f467b86 --- /dev/null +++ b/husky/ServerFrame.h @@ -0,0 +1,78 @@ +#ifndef HUSKY_SERVERFRAME_H +#define HUSKY_SERVERFRAME_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" +#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; + + 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: + ServerFrame(){}; + ~ServerFrame(){pthread_mutex_destroy(&m_pmAccept);}; + bool CreateServer(u_short nPort,u_short nThreadCount,IRequestHandler *pHandler); + bool CloseServer(); + bool RunServer(); + + 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 diff --git a/husky/ThreadManager.hpp b/husky/ThreadManager.hpp new file mode 100644 index 0000000..b3fce5f --- /dev/null +++ b/husky/ThreadManager.hpp @@ -0,0 +1,98 @@ +#ifndef HUSKY_THREAD_MANAGER_H +#define HUSKY_THREAD_MANAGER_H +#include +#include +#include +#include + +#define INFINITE 0 + +namespace Husky +{ + using namespace std; + + class ThreadManager + { + private: + typedef int HANDLE; + typedef int DWORD; + typedef void *(* PThreadFunc)(void* param); + public: + ThreadManager(){;} + ~ThreadManager(){} + + unsigned int HandleCount(){return m_vecHandle.size();} + + void clear() + { + m_vecHandle.clear(); + } + + HANDLE CreateThread( PThreadFunc pFunc,void *pPara) + { + pthread_t pt; + int nErrorCode=pthread_create(&pt,NULL,pFunc,pPara); + if(nErrorCode!=0) + return nErrorCode; + m_vecHandle.push_back(pt); //鍔犲叆绾跨▼鍒楄〃 涓篧aitForMultipleObjects鍑嗗 + return nErrorCode; + + } + + //hThread (thread handler) : 涓0鏃朵负榛樿鏈鍚庝竴涓姞鍏ョ鐞嗗櫒鐨勭嚎绋嬪彞鏌 + //dwMilliseconds绛夊緟鏃堕棿 : 鍗曚綅姣锛岄粯璁ゅ兼棤绌锋椂闂 + //return value : -1鍙ユ焺鏃犳晥锛屽叾浠栧 WaitForSingleObject鍑芥暟鐨勮繑鍥炲 + DWORD Wait(HANDLE hThread=0,DWORD dwMilliseconds=INFINITE ) + { + if( hThread==0)//鏈鍚庝竴涓姞鍏ョ殑绾跨▼ + { + if(!m_vecHandle.empty()) + { + return pthread_join(m_vecHandle.back(),NULL); + } + else + return -1; + } + else + { + if (find(m_vecHandle.begin(),m_vecHandle.end(),hThread)==m_vecHandle.end())//涓嶅瓨鍦ㄦ鍙ユ焺 + { + return -1; + } + + return pthread_join(hThread, NULL); + } + + } + + + //绛夊緟鎵鏈夌嚎绋嬫墽琛屽畬姣 + //bWaitAll鏄惁鎵鏈夌嚎绋 : 榛樿鍊1绛夊緟鎵鏈夌嚎绋,0鏈変换浣曠嚎绋嬬粨鏉燂紝姝ゅ嚱鏁拌繑鍥 + //dwMilliseconds : 鍗曚綅姣锛岄粯璁ゅ兼棤绌锋椂闂 + //return value : -1娌℃湁浠讳綍鍙ユ焺锛屽叾浠栧 WaitForMultipleObjects鍑芥暟鐨勮繑鍥炲 + DWORD WaitMultipleThread( bool bWaitAll=1,DWORD dwMilliseconds=INFINITE) + { + if (m_vecHandle.empty()) + return -1; + int nErrorcode; + for (uint i=0;i m_vecHandle; + + private: + ThreadManager(const ThreadManager&){;}// copy forbidden + void operator=(const ThreadManager &){}// copy forbidden + }; +} + + + +#endif diff --git a/husky/globals.h b/husky/globals.h new file mode 100644 index 0000000..3cf2318 --- /dev/null +++ b/husky/globals.h @@ -0,0 +1,26 @@ +#ifndef HUSKY_GLOBALS_H +#define HUSKY_GLOBALS_H +#include +#include +#include +#include +#include + + +namespace Husky +{ + + const char* const MASTER_PID_FILE= "masterDaemon.pid"; + + 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