服务端:
功能:保存所有客户端信息和在线状态,统一分配端口.对掉线的客户端信息通知到进程控制模块
ServerService.h
#ifndef _SERVERSERVICE_H_
#define _SERVERSERVICE_H_
#include <map>
#include <string>
#include <sstream>
#include <fstream>
#include "ace/TP_Reactor.h"
#include "ace/SOCK_Dgram.h"
#include "ace/Task.h"
namespace YB
{
const static ACE_UINT32 iLocalHostPort = 8001;
typedef unsigned char BYTE;
static ACE_Thread_Mutex slock;
typedef struct STAPPID_
{
std::string sIp; // 客户端IP
int iPort; // 客户端连接到服务端的端口
int ClientAcceptPort; // 服务端分配的客户端监听端口
BYTE byAppid; // 模块标识
BYTE byGroup; // 组号
int iTime; // 时计器,维护客户端在线状态
bool bOnline; // 在线状态
}STAppid;
/*
服务端UDP数据收发
*/
class CMain;
class CServerService: public ACE_Event_Handler
{
public:
// 构造、析构函数
CServerService();
~CServerService();
virtual ACE_HANDLE get_handle(void) const; // 继承基类
virtual int handle_input(ACE_HANDLE fd = ACE_INVALID_HANDLE); // 有网络数据到达
virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask); // 关闭网络监听
bool Open(CMain* cm);
void SendToAll(char* buf, int nSize); // 消息群发
int DeleteAppid(BYTE byappid, std::string sip); // 删除指定客户端信息
bool ReadServerIP(); // 读配置IP
private:
void UpdateClientAllSatte(STAppid stAppid, ACE_INET_Addr taddr); // 更新客户端状态
void UpdateState(YB::BYTE byappid); // 客户端在线
void MsgData(YB::BYTE byappid); // 消息报文
void ChackProtocol(const char* buf, const int nSize); // 解析报文
void ApplyConn(const char *buf, const int nSize); // 应答客户申请连接
void AllotPort(unsigned short &uiPort); // 检查分配客户端端口是否重复,并分配新的
BYTE checkFrame(unsigned char* uc_buf, unsigned short uc_length); // 帧校验
void fixFrame(unsigned char* uc_buf, unsigned char& uc_Length, // 组帧
unsigned char flag, unsigned char dest_addr, unsigned char src_addr);
void CheckAppid(BYTE byappid,std::string sIp);
public:
std::map<BYTE, STAppid> mpInfo; // 注册客户端信息表
private:
ACE_INET_Addr addr;
ACE_SOCK_Dgram udp;
std::string sServerIP;
unsigned short usiPort; // 分配客户端端口值
STAppid stAppid;
int iPortCount;
CMain* cmn;
};
// 定时器类,监视在线客户端,
class CTaskTimer : public ACE_Task_Base
{
public:
// 构造、析构函数
CTaskTimer(){timeid = 0;};
virtual ~CTaskTimer(){};
virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask); // 关闭网络监听
public:
bool Open(CServerService *udp);
int handle_timeout(const ACE_Time_Value ¤t_time, const void *act = 0);// 定时器,清理掉线客户端
private:
CServerService *sudp;
long timeid;
};
// 主调类,负责启动定时器和网络监听
class CMain : public ACE_Task_Base
{
public:
// 构造、析构函数
CMain(){};
~CMain(){};
public:
bool Open();
int Close();
private:
CServerService *serudp;
CTaskTimer *taskTimer;
};
}
#endif // end of _SERVERSERVICE_H_
ServerService.cpp
#include "./ServerService.h"
using namespace YB;
bool CMain::Open()
{
ACE_NEW_RETURN(serudp, CServerService, false);
ACE_NEW_RETURN(taskTimer, CTaskTimer, false);
serudp->reactor(ACE_Reactor::instance());
if (!serudp->Open(this)) return false;
taskTimer->reactor(ACE_Reactor::instance());
if (!taskTimer->Open(serudp)) return false;
ACE_OS::sleep(ACE_Time_Value(0, 10000)); // 等待10毫秒
ACE_Reactor::instance()->run_reactor_event_loop(); // 启动线程
return true;
}
int CMain::Close()
{
taskTimer->handle_close(ACE_INVALID_HANDLE, 0);
serudp->handle_close(ACE_INVALID_HANDLE, 0);
if (ACE_Reactor::instance()->reactor_event_loop_done() != 1)
{
ACE_Reactor::instance()->end_reactor_event_loop();
}
return 0;
}
///
CServerService::CServerService()
{
usiPort = 20000; // 初使分配客户端端口值
iPortCount = 0;
}
CServerService::~CServerService()
{
}
bool CServerService::ReadServerIP()
{
std::ifstream fle("ServerIp.txt", std::ios::in);
if (!fle) return false;
std::ostringstream seamServerIP;
seamServerIP<<fle.rdbuf();
sServerIP = seamServerIP.str();
fle.close();
return true;
}
bool CServerService::Open(CMain* cm)
{
if (!ReadServerIP()) return false;
this->addr.set(iLocalHostPort, sServerIP.c_str());//, ACE_LOCALHOST
this->udp.open(addr);
this->reactor()->register_handler(this, ACE_Event_Handler::READ_MASK);
cmn = cm;
return true;
}
ACE_HANDLE CServerService::get_handle() const
{
return this->udp.get_handle();
}
int CServerService::handle_input(ACE_HANDLE)
{
ACE_INET_Addr taddr;
char buf[255] = {0};
int isize = 0;
isize = this->udp.recv(buf, 255, taddr);
stAppid.iPort = taddr.get_port_number();
stAppid.sIp = taddr.get_host_addr();
if (isize > 0 && isize < 255) ChackProtocol(buf, isize);
return 0;
}
int CServerService::handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask)
{
if (this->udp.get_handle() != ACE_INVALID_HANDLE)
{
ACE_Reactor_Mask m = ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL;
this->reactor()->remove_handler(this, m);
this->udp.close();
}
delete this;
return 0;
}
unsigned char CServerService::checkFrame(unsigned char* uc_buf, unsigned short uc_length)
{
//检查报文
return 1;
}
void CServerService::fixFrame( unsigned char* uc_buf,
unsigned char& uc_Length,
unsigned char flag,
unsigned char dest_addr,
unsigned char src_addr)
{
//组装报文
return ;
}
void CServerService::ChackProtocol(const char* buf, const int nSize)
{
YB::BYTE *p = (YB::BYTE*)buf;
if (checkFrame(p, nSize)) return;
switch (*(p + 11))
{
case 0x00: // 心跳
{
UpdateState(*(p + 6));
if (*(p + 2) == 0x02) MsgData(*(p + 6));
break;
}
case 0x01: // 我要处理的类型
{
switch (*(p + 15))
{
case 0x00: // 正常退出,离线状态
{
DeleteAppid(*(p + 23), stAppid.sIp);
break;
}
case 0x02: // 申请连接
{
ApplyConn(buf, nSize);
break;
}
default:
break;
}
break;
}
case 0x02: // 退出
{
if (*(p + 15) == 0x04 && *(p + 6) == 0x01) cmn->Close();
break;
}
default:
break;
}
}
void CServerService::ApplyConn(const char *buf, const int nSize)
{
ACE_INET_Addr taddr;
YB::BYTE isize = 0x0C;
char puf[255] = {0};
char *p = (char*)buf;
AllotPort(usiPort);
stAppid.ClientAcceptPort = usiPort;
stAppid.byAppid = *(p + 6);
stAppid.byGroup = *(p + 16);
CheckAppid( stAppid.byAppid,stAppid.sIp.c_str() );
taddr.set(usiPort, stAppid.sIp.c_str());
ACE_UINT32 ip = taddr.get_ip_address();
u_short iprt = taddr.get_port_number();
/*组帧
strcpy(puf, "/x01/x01/x01/x0C/x03");
puf[5] = stAppid.byGroup;
memcpy(puf + 6, &ip, sizeof(ACE_UINT32));
memcpy(puf + 6 + sizeof(ACE_UINT32), &iprt, sizeof(u_short));
fixFrame((unsigned char*)puf, isize, 0x01, stAppid.byAppid, 0x04);
taddr.set(stAppid.iPort, stAppid.sIp.c_str());
*/
this->udp.send(puf, isize, taddr);
/*
// 向其他客户端更新信息
isize = 0x0D;
memset(puf, 0x00, 255);
strcpy(puf, "/x01/x01/x01/x0D/x01");
puf[5] = stAppid.byGroup;
memcpy(puf + 6, &ip, sizeof(ACE_UINT32));
memcpy(puf + 6 + sizeof(ACE_UINT32), &iprt, sizeof(u_short));
memcpy(puf + 6 + sizeof(ACE_UINT32) + sizeof(u_