1. Server.h
#ifndef SOCKET_SERVER_H
#define SOCKET_SERVER_H
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/time.h>
#include <pthread.h>
#include <unistd.h>
#include <execinfo.h>
#include <signal.h>
#include "./Typedef.h"
#include "Print.h"
#define SOCKET_BUFFER 2048
#define INADDR_ANY ((in_addr_t) 0x00000000)
#define THRD_FLAG_FREE 0 //线程空闲
#define THRD_FLAG_USAGE 1 //线程使用
#define THRD_FLAG_EXITING 2 //线程等待退出
//Socket参数 + 线程参数
typedef struct {
BYTE bFlag; //线程状态标志
pthread_attr_t att; //线程属性
pthread_t tThrd; //线程句柄
int iFd; //socket句柄
struct sockaddr_in addr; //socket信息(地址+端口)
socklen_t addrLen; //socket信息长度(地址+端口)
}TSktThrdPara;
class CServer{
private:
CPrint *m_pCPrint;
TSktThrdPara m_TSrvPara;
TSktThrdPara *m_pTCltPara=NULL;
DWORD m_dwSrvIP;
DWORD m_dwSrvPort;
DWORD m_dwConnectClients;
int m_iCurIdx;
TSktThrdPara *GetSktThrdPara();
void UpdSktThrdPara(TSktThrdPara *pTSktThrdPara, BYTE bFlag);
void CltFunc();
void SrvFunc();
static void *CltThrd(void *pvData);
static void *SrvThrd(void *pvData);
public:
CServer();
~CServer();
bool InitSrv(DWORD dwSrvIP, DWORD dwPort, DWORD dwConnectClients);
bool CloseSrv();
virtual int ProcSrv(BYTE *pbRxBuf, int iRxLen, BYTE *pbTxBuf, int iTxLen){return -1;};
};
#endif //SOCKET_SERVER_H
2. Server.cpp
#include "SocketServer.h"
CServer::CServer()
{
m_pCPrint = new CPrint();
memset((BYTE*)&m_TSrvPara, 0, sizeof(m_TSrvPara));
}
CServer::~CServer()
{
delete m_pCPrint;
}
TSktThrdPara *CServer::GetSktThrdPara()
{
int idx;
for (idx=0; idx<m_dwConnectClients; idx++)
{
if (&m_pTCltPara[idx] != NULL)
{
if (m_pTCltPara[idx].bFlag == THRD_FLAG_EXITING)
m_pTCltPara[idx].bFlag = THRD_FLAG_FREE;
if (m_pTCltPara[idx].bFlag == THRD_FLAG_FREE)
{
m_iCurIdx = idx;
return &m_pTCltPara[idx];
}
}
}
return NULL;
}
void CServer::UpdSktThrdPara(TSktThrdPara *pTSktThrdPara, BYTE bFlag)
{
pTSktThrdPara->bFlag = bFlag;
}
void *CServer::CltThrd(void *pvData)
{
((CServer*)pvData)->CltFunc();
}
void *CServer::SrvThrd(void *pvData)
{
((CServer*)pvData)->SrvFunc();
}
void CServer::CltFunc()
{
TSktThrdPara *pSktThrdPara = &this->m_pTCltPara[this->m_iCurIdx];
BYTE bRxBuf[SOCKET_BUFFER], bTxBuf[SOCKET_BUFFER];
int iRet;
m_pCPrint->PrintStr("CltThrd start: iCltFd=%d.\n", pSktThrdPara->iFd);
while (1)
{
memset(bRxBuf, 0, sizeof(bRxBuf));
if ((iRet=recv(pSktThrdPara->iFd, bRxBuf, sizeof(bRxBuf), 0)) > 0)
{
memset(bTxBuf, 0, sizeof(bTxBuf));
if ((iRet=ProcSrv(bRxBuf, iRet, bTxBuf, sizeof(bTxBuf))) > 0)
{
if ((iRet=send(pSktThrdPara->iFd, bTxBuf, iRet, 0)) < 0)
m_pCPrint->PrintStr("CltThrd(fd=%d):send \n", pSktThrdPara->iFd, strerror(iRet));
}
}
else if (iRet == 0)
{
break;
}
}
UpdSktThrdPara(pSktThrdPara, THRD_FLAG_EXITING);
close(pSktThrdPara->iFd);
}
void CServer::SrvFunc()
{
CServer *pCSrv = (CServer *)this;
TSktThrdPara *pSrvPara = &(pCSrv->m_TSrvPara);
TSktThrdPara *pSktThrdPara;
m_pCPrint->PrintStr("SrvThrd start: iSrvFd=%d.\n", pSrvPara->iFd);
while (1)
{
if ((pSktThrdPara=pCSrv->GetSktThrdPara()) != NULL)
{
pSktThrdPara->addrLen = sizeof(pSktThrdPara->addr);
pSktThrdPara->iFd = accept(pSrvPara->iFd, (struct sockaddr*)&pSktThrdPara->addr, &pSktThrdPara->addrLen);
if (pSktThrdPara->iFd > 0)
{
pthread_attr_init(&pSktThrdPara->att);
pthread_attr_setdetachstate(&pSktThrdPara->att, PTHREAD_CREATE_DETACHED); //设置线程属性,线程退出时自动回收资源
pthread_create(&pSktThrdPara->tThrd, &pSktThrdPara->att, CltThrd, pSktThrdPara);
}
else
{
m_pCPrint->PrintStr("SrvThrd:accept %s\n", strerror(pSktThrdPara->iFd));
}
}
usleep(100*1000);
}
}
bool CServer::InitSrv(DWORD dwSrvIP, DWORD dwPort, DWORD dwConnectClients)
{
int iRet;
m_dwSrvIP = dwSrvIP;
m_dwSrvPort = dwPort;
m_dwConnectClients = dwConnectClients;
if((m_TSrvPara.iFd=socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
m_pCPrint->PrintStr("InitSrv:socket %s", strerror(m_TSrvPara.iFd));
return false;
}
m_TSrvPara.addr.sin_family = AF_INET;
m_TSrvPara.addr.sin_addr.s_addr = (m_dwSrvIP==0)? htonl(INADDR_ANY) : htonl(m_dwSrvIP);
m_TSrvPara.addr.sin_port = m_dwSrvPort;
m_TSrvPara.addrLen=sizeof(m_TSrvPara.addr);
if ((iRet=bind(m_TSrvPara.iFd, (struct sockaddr *)&m_TSrvPara.addr, m_TSrvPara.addrLen)) < 0)
{
m_pCPrint->PrintStr("InitSrv:bind %s", strerror(iRet));
close(m_TSrvPara.iFd);
return false;
}
if((listen(m_TSrvPara.iFd, m_dwConnectClients)) < 0)
{
m_pCPrint->PrintStr("InitSrv:listen %s", strerror(iRet));
close(m_TSrvPara.iFd);
return false;
}
m_pTCltPara = new TSktThrdPara[m_dwConnectClients];
pthread_attr_init(&m_TSrvPara.att);
pthread_attr_setdetachstate(&m_TSrvPara.att, PTHREAD_CREATE_DETACHED); //设置线程属性,线程退出时自动回收资源
pthread_create(&m_TSrvPara.tThrd, &m_TSrvPara.att, SrvThrd, (void*)this); //创建服务端线程
return true;
}
bool CServer::CloseSrv()
{
bool fRet = true;
if (m_TSrvPara.iFd > 0)
{
fRet = close(m_TSrvPara.iFd);
m_TSrvPara.iFd = 0;
}
if (m_pTCltPara != NULL)
delete[] m_pTCltPara;
return fRet;
}
3. 使用
#由于该接口类实现了去耦,其它模块在调用时通过继承该类即可,然后重写虚函数ProcSrv()即可。。。