0
点赞
收藏
分享

微信扫一扫

socket 服务端类模块封装

双井暮色 2022-09-19 阅读 42


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()即可。。。

 

举报

相关推荐

0 条评论