init
This commit is contained in:
399
Gateway/gateway/client/client.cc
Normal file
399
Gateway/gateway/client/client.cc
Normal file
@@ -0,0 +1,399 @@
|
||||
#include "StdAfx.h"
|
||||
#include "client.h"
|
||||
#include "base/sha1.h"
|
||||
#include "base64.h"
|
||||
|
||||
BaseAllocator Client::alloc("ClientAlloc");
|
||||
Client::Client(GameClientMgr *cli_mgr, SOCKET s, sockaddr_in* addr) {
|
||||
shake_hands_ = false;
|
||||
fd_ = s;
|
||||
cli_mgr_ = cli_mgr;
|
||||
send_packet_ = new DataPacket(&alloc);
|
||||
send_packet_->reserve(SEND_PACKET_MAX);
|
||||
send_packet_->setLength(0);
|
||||
memcpy(&remote_addr_, addr, sizeof(sockaddr_in));
|
||||
net_id_.socket_ = s;
|
||||
conn_status_ = ConnStatusDef::CS_CONNED;
|
||||
skey_ = 0;
|
||||
is_close_ = false;
|
||||
real_ip[0] = 0;
|
||||
}
|
||||
|
||||
Client ::~Client() {
|
||||
for (auto it : recv_list_) {
|
||||
SafeDelete(it);
|
||||
}
|
||||
SafeDelete(send_packet_);
|
||||
recv_list_.clear();
|
||||
for (auto it : gw_recv_list_) {
|
||||
SafeDelete(it);
|
||||
}
|
||||
real_ip[0] = 0;
|
||||
}
|
||||
|
||||
int Client::SetBlockMode(const bool block) {
|
||||
unsigned long flag = block ? 0 : 1;
|
||||
#ifdef _MSC_VER
|
||||
return ioctlsocket(fd_, FIONBIO, &flag);
|
||||
#else
|
||||
return ioctl(fd_, FIONBIO, &flag);//改为非阻塞;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Client::RecvData(void) {
|
||||
if (is_close_) return;
|
||||
static char buf[1024];
|
||||
while (true) {
|
||||
int buflen = recv(fd_, buf, sizeof(buf), 0);
|
||||
if (buflen < 0) {
|
||||
// 由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可读
|
||||
// 在这里就当作是该次事件已处理
|
||||
#ifdef _MSC_VER
|
||||
if (WSAGetLastError() == WSAECONNABORTED) {
|
||||
Close();
|
||||
return;
|
||||
} else if (WSAGetLastError() == WSAEWOULDBLOCK) {
|
||||
#else
|
||||
if (WSAGetLastError() == EINPROGRESS || WSAGetLastError() == EAGAIN) {
|
||||
#endif
|
||||
break;
|
||||
} else {
|
||||
MSG_ERR("not handle errno:[%d]%s", WSAGetLastError(), strerror(WSAGetLastError()));
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
} else if (buflen == 0) {
|
||||
// 这里表示对端的socket已正常关闭.
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
if (shake_hands_) {
|
||||
DataPacket* dp = new DataPacket(&alloc);
|
||||
dp->writeBuf(buf, buflen);
|
||||
dp->setPosition(0);
|
||||
recv_list_.push_back(dp);
|
||||
} else {
|
||||
//进行websocket握手
|
||||
ShakeHandsHandle(buf, buflen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Client::SendData(void) {
|
||||
size_t splen = send_packet_->getAvaliableLength();
|
||||
if (splen <= 0) { return true; }
|
||||
int lsed = send(fd_, send_packet_->getOffsetPtr(), (int)splen, 0);
|
||||
if(lsed <= 0) { return true; }
|
||||
if (lsed < splen) {
|
||||
send_packet_->setPosition(send_packet_->getPosition() + lsed);
|
||||
return false;
|
||||
} else {
|
||||
send_packet_->setLength(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::WriteEvent(void) {
|
||||
if (is_close_) return;
|
||||
DataPacket* dp = NULL;
|
||||
while (true) {
|
||||
if (gw_recv_list_.empty()) { break; }
|
||||
dp = *(gw_recv_list_.begin());
|
||||
gw_recv_list_.pop_front();
|
||||
FlushWsPack(dp->getOffsetPtr(), dp->getAvaliableLength());
|
||||
SafeDelete(dp);
|
||||
}
|
||||
if(send_packet_->getAvaliableLength() > 0) {
|
||||
cli_mgr_->HaveData(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Flush(const char *buf, size_t len) {
|
||||
if (send_packet_->getAvaliableLength() + len > SEND_PACKET_MAX) {
|
||||
MSG_ERR("send packet is max, fd:%d", fd_);
|
||||
Close();
|
||||
return;
|
||||
} else {
|
||||
size_t pos = send_packet_->getPosition();
|
||||
send_packet_->setPosition(pos + send_packet_->getAvaliableLength());
|
||||
send_packet_->writeBuf(buf, len);
|
||||
send_packet_->setPosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendNewSession(void) {
|
||||
static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient();
|
||||
DataPacket &dp = wgc->AllocProtoPacket(GM_OPEN,net_id_.socket_,net_id_.index_,net_id_.gate_id_);
|
||||
if (real_ip[0] != 0)
|
||||
dp.writeBuf(real_ip, 32);
|
||||
else
|
||||
dp.writeBuf(inet_ntoa(remote_addr_.sin_addr), 32);
|
||||
wgc->flushProtoPacket(dp);
|
||||
OutputMsg(rmTip, _T("[Login] (2) 握手成功,通知LogicServer创建一个玩家Gate: gatekey(%d),socket(%lld),GateIdx(%d),LogicIdx(%d),CurrentThreadId(%d)。"),
|
||||
skey_, net_id_.socket_, net_id_.index_, net_id_.gate_id_, GetCurrentThreadId());
|
||||
}
|
||||
|
||||
void Client::SendSessionClose(void) {
|
||||
static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient();
|
||||
DataPacket &dp = wgc->AllocProtoPacket(GM_CLOSE,net_id_.socket_,net_id_.index_,net_id_.gate_id_);
|
||||
wgc->flushProtoPacket(dp);
|
||||
}
|
||||
|
||||
void Client::Close(void) {
|
||||
MSG_ERR("close client, fd:%d,index:%d", net_id_.socket_, net_id_.index_);
|
||||
cli_mgr_->CloseClient(this);
|
||||
SendSessionClose();
|
||||
is_close_ = true;
|
||||
}
|
||||
|
||||
#define WEB_SOCKET_HANDS_RE "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n"
|
||||
#define MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
void Client::ShakeHandsHandle(const char* buf, int buflen) {
|
||||
char key[512]; memset(key, 0, 512);
|
||||
for (int i = 0; i < buflen; ++i)
|
||||
{
|
||||
if (FindHttpParam("Sec-WebSocket-Key", buf+i)) {
|
||||
short k = i + 17, ki = 0;
|
||||
while(*(buf + k) != '\r' && *(buf + k) != '\n' && *(buf + k) != '\0') {
|
||||
if (*(buf + k) == ':' || *(buf + k) == ' '){
|
||||
++k; continue;
|
||||
} else {
|
||||
key[ki++] = *(buf + k);
|
||||
}
|
||||
++k;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memset(real_ip, 0, sizeof(real_ip));
|
||||
for (int i = 0; i < buflen; ++i)
|
||||
{
|
||||
if (FindHttpParam("X-Real-IP", buf+i)) {
|
||||
short k = i + 9, ki = 0;
|
||||
while(*(buf + k) != '\r' && *(buf + k) != '\n' && *(buf + k) != '\0') {
|
||||
if (*(buf + k) == ':' || *(buf + k) == ' '){
|
||||
++k; continue;
|
||||
} else {
|
||||
real_ip[ki++] = *(buf + k);
|
||||
}
|
||||
++k;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//MSG_LOG("key:%s...", key);
|
||||
memcpy(key + strlen(key), MAGIC_KEY, sizeof(MAGIC_KEY));
|
||||
//MSG_LOG("megerkey:%s...", key);
|
||||
//求哈希1
|
||||
SHA1 sha;
|
||||
unsigned int message_digest[5];
|
||||
sha.Reset();
|
||||
sha << key;
|
||||
sha.Result(message_digest);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
message_digest[i] = htonl(message_digest[i]);
|
||||
}
|
||||
|
||||
memset(key, 0, 512);
|
||||
base64_encode(key, reinterpret_cast<const char*>(message_digest), 20);
|
||||
char http_res[512] = "";
|
||||
sprintf(http_res, WEB_SOCKET_HANDS_RE, key);
|
||||
Flush(http_res, strlen(http_res));
|
||||
//MSG_LOG("res:%s...",http_res);//fkYTdNEVkParesYkrM4S
|
||||
SendData();
|
||||
shake_hands_ = true;
|
||||
SendNewSession();//发送到gameworld新增连接
|
||||
}
|
||||
|
||||
void Client::PacketHandle(void) {
|
||||
if (is_close_) return;
|
||||
while (!recv_list_.empty()) {
|
||||
auto dpit = recv_list_.begin();
|
||||
DataPacket* dp = *dpit;
|
||||
//读取websocket固定包头
|
||||
if (!ws_head_.rh) {
|
||||
//这个包不够一个头部的大小
|
||||
if (dp->getAvaliableLength() < 2) {
|
||||
if (MergePacketList(dpit)) continue;
|
||||
else break;
|
||||
}
|
||||
//读取
|
||||
uint8_t head = 0;
|
||||
dp->readBuf(&head, 1);
|
||||
ws_head_.fin = head >> 7;
|
||||
ws_head_.opcode = head & 0xF;
|
||||
dp->readBuf(&head, 1);
|
||||
ws_head_.len = head & 0x7F;
|
||||
ws_head_.mask = head >> 7;
|
||||
ws_head_.rh = 1;//标记头部读取完成
|
||||
}
|
||||
//读取长度
|
||||
if (!ws_head_.rl) {
|
||||
uint8_t nsize = ws_head_.GetLenNeedByte();
|
||||
if (nsize) {
|
||||
//这个包不够一个长度
|
||||
if (dp->getAvaliableLength() < nsize) {
|
||||
if (MergePacketList(dpit)) continue;
|
||||
else break;
|
||||
}
|
||||
if (nsize == 2) {
|
||||
(*dp) >> ws_head_.ex_len.v16;
|
||||
ws_head_.ex_len.v16 = ntohs(ws_head_.ex_len.v16);
|
||||
} else {
|
||||
(*dp) >> ws_head_.ex_len.v32;
|
||||
ws_head_.ex_len.v32 = ntohl((u_long)ws_head_.ex_len.v32);
|
||||
}
|
||||
}
|
||||
ws_head_.rl = 1;
|
||||
}
|
||||
//读取MKEY
|
||||
if (!ws_head_.rk) {
|
||||
if (ws_head_.mask) {
|
||||
//这个包不够一个key
|
||||
if (dp->getAvaliableLength() < 4) {
|
||||
if (MergePacketList(dpit)) continue;
|
||||
else break;
|
||||
}
|
||||
(*dp) >> ws_head_.mkey[0];
|
||||
(*dp) >> ws_head_.mkey[1];
|
||||
(*dp) >> ws_head_.mkey[2];
|
||||
(*dp) >> ws_head_.mkey[3];
|
||||
}
|
||||
ws_head_.rk = 1;
|
||||
}
|
||||
//读取数据段
|
||||
uint64_t data_len = ws_head_.GetLen();
|
||||
if (dp->getAvaliableLength() < data_len) {
|
||||
if (MergePacketList(dpit)) continue;
|
||||
else break;
|
||||
}
|
||||
|
||||
if (ws_head_.mask) {
|
||||
char* dptr = dp->getOffsetPtr();
|
||||
for (size_t i = 0; i < data_len; ++i) {
|
||||
dptr[i] = dptr[i] ^ ws_head_.mkey[i % 4];
|
||||
}
|
||||
}
|
||||
|
||||
if (!OnRecv(dp->getOffsetPtr(), data_len)) {
|
||||
return;
|
||||
}
|
||||
ws_head_.reset();
|
||||
dp->adjustOffset(data_len);
|
||||
//这个包读取完了
|
||||
if (dp->getAvaliableLength() <= 0) {
|
||||
recv_list_.pop_front();
|
||||
SafeDelete(dp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Client::OnRecv(const char* buf, size_t size) {
|
||||
|
||||
if (conn_status_ == CS_COMMUNICATE) {
|
||||
if (ws_head_.opcode == OPCODE_CLR) {
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
if (size < 4 + 2) {
|
||||
MSG_ERR("size is min");
|
||||
return true;
|
||||
}
|
||||
|
||||
//截去key
|
||||
unsigned short tag = *((unsigned short*)buf);
|
||||
if (tag != skey_) {
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
char* pdata = (char*)buf + sizeof(unsigned short);
|
||||
size -= 2;
|
||||
|
||||
//截去验证
|
||||
uint32_t check = *((uint32_t*)pdata);
|
||||
pdata = pdata + sizeof(uint32_t);
|
||||
size -= 4;
|
||||
|
||||
//发送给游戏服
|
||||
static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient();
|
||||
DataPacket &pack = wgc->AllocProtoPacket(GM_DATA,net_id_.socket_,net_id_.index_,net_id_.gate_id_);
|
||||
#ifdef _DEBUG
|
||||
const unsigned char* proto = pdata;
|
||||
OutputMsg(rmTip, "<[sock:%d,idx:%d] Recv(%d,%d)", fd_, GetSessionId(), *proto, *(proto+1));
|
||||
#endif
|
||||
pack.writeBuf(pdata, size);
|
||||
wgc->flushProtoPacket(pack);
|
||||
//MSG_ERR("size is [%d + 4 + 2]", size);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (conn_status_ == CS_CONNED) { //刚连接上来
|
||||
uint32_t tag = *((uint32_t*)buf);
|
||||
if (tag != DEFAULT_TAG) {
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
skey_ = wrand(SHRT_MAX);
|
||||
FlushWsPack((char *)&skey_, 2);
|
||||
SendData();
|
||||
conn_status_ = CS_COMMUNICATE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::FlushWsPack(const char* buf, size_t size) {
|
||||
static DataPacket pack(&alloc);
|
||||
pack.setLength(0);
|
||||
pack << (uint8_t)0x82;//写头部
|
||||
//写长度
|
||||
if (size >= 126) {//7位放不下
|
||||
if (size <= 0xFFFF) {//16位放
|
||||
pack << (uint8_t)126;
|
||||
pack << (uint16_t)htons((u_short)size);
|
||||
} else {//64位放
|
||||
pack << (uint8_t)127;
|
||||
pack << (uint64_t)OrderSwap64(size);
|
||||
}
|
||||
} else {
|
||||
pack << (uint8_t)size;
|
||||
}
|
||||
//写数据
|
||||
pack.writeBuf(buf, size);
|
||||
pack.setPosition(0);
|
||||
Flush(pack.getOffsetPtr(), pack.getAvaliableLength());
|
||||
}
|
||||
|
||||
void Client::OnGameWorldRecv(const char* buf, size_t size) {
|
||||
DataPacket *dp = new DataPacket(&alloc);
|
||||
(*dp) << (uint16_t)skey_;
|
||||
#ifdef _DEBUG
|
||||
const unsigned char* proto = buf;
|
||||
OutputMsg(rmTip, ">[sock:%d,idx:%d] Send(%d,%d)", fd_, GetSessionId(), *proto, *(proto+1));
|
||||
#endif
|
||||
dp->writeBuf(buf, size);
|
||||
dp->setPosition(0);
|
||||
gw_recv_list_.push_back(dp);
|
||||
}
|
||||
|
||||
bool Client::MergePacketList(std::list<DataPacket*>::iterator &dpit) {
|
||||
auto sdpit = dpit++;
|
||||
if (dpit == recv_list_.end()) return false;
|
||||
DataPacket* sdp = *sdpit;
|
||||
//合并第二个到第一个
|
||||
sdp->writeBuf((*dpit)->getOffsetPtr(), (*dpit)->getAvaliableLength());
|
||||
SafeDelete((*dpit));
|
||||
recv_list_.erase(dpit);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Client::FindHttpParam(const char * param, const char * buf) {
|
||||
while (*param == *buf) {
|
||||
if (*(param + 1) == '\0') return true;
|
||||
++param; ++buf;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
106
Gateway/gateway/client/client.h
Normal file
106
Gateway/gateway/client/client.h
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
|
||||
#define SEND_PACKET_MAX 1024*1024*8
|
||||
#define DEFAULT_TAG 0xCA0FFFFF
|
||||
|
||||
enum WebSocketOpcode { //操作码定义类型
|
||||
OPCODE_MID = 0x0,//标识一个中间数据包
|
||||
OPCODE_TXT = 0x1,//标识一个text类型数据包
|
||||
OPCODE_BIN = 0x2,//标识一个binary类型数据包
|
||||
//0x3 - 7:保留
|
||||
OPCODE_CLR = 0x8,//标识一个断开连接类型数据包
|
||||
OPCODE_PIN = 0x9,//标识一个ping类型数据包
|
||||
OPCODE_PON = 0xA,//表示一个pong类型数据包
|
||||
};
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct WebSocketHead {
|
||||
uint8_t fin : 1;//标识是否为此消息的最后一个数据包
|
||||
uint8_t rsv1 : 1;//保留位1
|
||||
uint8_t rsv2 : 1;//保留位2
|
||||
uint8_t rsv3 : 1;//保留位3
|
||||
uint8_t opcode : 4;//操作码
|
||||
|
||||
uint8_t mask : 1; //是否需要掩码
|
||||
uint8_t len : 7;//长度
|
||||
union {
|
||||
uint16_t v16;//长度为126时
|
||||
uint32_t v32;//长度为127时
|
||||
} ex_len;
|
||||
uint8_t mkey[4];
|
||||
uint8_t rh : 1;//head读取完成
|
||||
uint8_t rl : 1;//len读取完成
|
||||
uint8_t rk : 1;//mkey读取完成
|
||||
uint8_t rs : 5;//扩展保留
|
||||
WebSocketHead(void) { reset(); }
|
||||
void reset(void) { memset(this,0,sizeof(WebSocketHead)); }
|
||||
inline uint32_t GetLen(void) {
|
||||
if (len == 126) {
|
||||
return ex_len.v16;
|
||||
} else if (len == 127) {
|
||||
return ex_len.v32;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
inline uint8_t GetLenNeedByte(void) {
|
||||
if (len == 126) {
|
||||
return 2;
|
||||
} else if (len == 127) {
|
||||
return 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
enum ConnStatusDef {
|
||||
CS_CONNED,//连接上
|
||||
CS_COMMUNICATE,//通信状态
|
||||
};
|
||||
typedef std::list<DataPacket*> DataPacketList;
|
||||
class Client {
|
||||
public:
|
||||
Client(GameClientMgr *cli_mgr, SOCKET s, sockaddr_in* addr);
|
||||
~Client();
|
||||
|
||||
//设置阻塞模式。true表示阻塞,false表示非阻塞,返回值为socket错误号,0表示成功
|
||||
int SetBlockMode(const bool block);
|
||||
void SetSessionId(const uint16_t sid) { net_id_.index_ = sid; }
|
||||
uint16_t GetSessionId(void) { return net_id_.index_; }
|
||||
NetId &GetNetId(void) { return net_id_; }
|
||||
void RecvData(void);
|
||||
bool SendData(void);
|
||||
void WriteEvent(void);
|
||||
void Flush(const char *buf, size_t len);
|
||||
void SendNewSession(void);
|
||||
void SendSessionClose(void);
|
||||
void Close(void);
|
||||
bool OnRecv(const char* buf, size_t size);
|
||||
void FlushWsPack(const char* buf, size_t size);
|
||||
void OnGameWorldRecv(const char* buf, size_t size);
|
||||
inline SOCKET GetFd(void) { return fd_; }
|
||||
inline bool IsClose(void) { return is_close_; }
|
||||
void PacketHandle(void);
|
||||
uint16_t GetSKey() { return skey_; }
|
||||
protected:
|
||||
void ShakeHandsHandle(const char* buf, int buflen);
|
||||
private:
|
||||
inline bool MergePacketList(std::list<DataPacket*>::iterator &dpit);
|
||||
bool FindHttpParam(const char* param, const char* buf);
|
||||
|
||||
bool shake_hands_;//是否已经握手
|
||||
SOCKET fd_; //套接字
|
||||
bool is_close_; //是否已经关闭连接
|
||||
sockaddr_in remote_addr_;//远程地址
|
||||
DataPacketList recv_list_;//收到的包列表
|
||||
DataPacket* send_packet_;//需要发包的缓冲区
|
||||
DataPacketList gw_recv_list_;//从游戏服收到的包列表
|
||||
WebSocketHead ws_head_;//包头
|
||||
NetId net_id_;
|
||||
uint8_t conn_status_;//连接状态
|
||||
uint16_t skey_;//服务端KEY
|
||||
static BaseAllocator alloc;
|
||||
GameClientMgr* cli_mgr_;
|
||||
char real_ip[64];
|
||||
};
|
||||
67
Gateway/gateway/client/client_obj_mgr.cc
Normal file
67
Gateway/gateway/client/client_obj_mgr.cc
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "StdAfx.h"
|
||||
#include "client_obj_mgr.h"
|
||||
#include <map>
|
||||
|
||||
ClientObjMgr::ClientObjMgr() {
|
||||
cur_idx_ = 0;
|
||||
max_session_ = 0;
|
||||
}
|
||||
|
||||
|
||||
ClientObjMgr::~ClientObjMgr() {
|
||||
flush();
|
||||
for (auto cli:client_list_) {
|
||||
SafeDelete(cli.second);
|
||||
}
|
||||
client_list_.clear();
|
||||
}
|
||||
|
||||
void ClientObjMgr::SetMaxSession(int max_session) {
|
||||
max_session_ = max_session;
|
||||
}
|
||||
|
||||
bool ClientObjMgr::setNewClient(Client *cli) {
|
||||
client_lock_.Lock();
|
||||
if (max_session_ <= cur_idx_) return false;
|
||||
uint16_t index = 0;
|
||||
if (free_cli_idx_.empty()) {
|
||||
index = cur_idx_++;
|
||||
} else {
|
||||
index = free_cli_idx_.front();
|
||||
free_cli_idx_.pop_front();
|
||||
}
|
||||
cli->SetSessionId(index);
|
||||
client_append_list_.push_back(cli);
|
||||
client_lock_.Unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientObjMgr::flush(void) {
|
||||
client_lock_.Lock();
|
||||
for (auto it:client_append_list_) {
|
||||
client_list_.insert(std::make_pair(it->GetSessionId(), it));
|
||||
}
|
||||
client_append_list_.clear();
|
||||
client_lock_.Unlock();
|
||||
}
|
||||
|
||||
Client* ClientObjMgr::get(uint16_t index) {
|
||||
auto it = client_list_.find(index);
|
||||
if (it == client_list_.end()) return NULL;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Client * ClientObjMgr::remove(uint16_t index) {
|
||||
auto it = client_list_.find(index);
|
||||
if (it == client_list_.end()) return NULL;
|
||||
Client *cli = it->second;
|
||||
client_list_.erase(it);
|
||||
client_lock_.Lock();
|
||||
if (index == cur_idx_ - 1) {
|
||||
--cur_idx_;
|
||||
} else {
|
||||
free_cli_idx_.push_back(index);
|
||||
}
|
||||
client_lock_.Unlock();
|
||||
return cli;
|
||||
}
|
||||
24
Gateway/gateway/client/client_obj_mgr.h
Normal file
24
Gateway/gateway/client/client_obj_mgr.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include <map>
|
||||
class ClientObjMgr {
|
||||
public:
|
||||
ClientObjMgr();
|
||||
~ClientObjMgr();
|
||||
|
||||
void SetMaxSession(int max_session);
|
||||
bool setNewClient(Client *cli);
|
||||
void flush(void);
|
||||
std::map<uint16_t, Client*> &getClientMap(void) {
|
||||
return client_list_;
|
||||
}
|
||||
Client* get(uint16_t index);
|
||||
Client* remove(uint16_t index);
|
||||
private:
|
||||
uint16_t max_session_;//最大客户端连接数
|
||||
uint16_t cur_idx_;
|
||||
std::list<uint16_t> free_cli_idx_;//空闲的客户端索引
|
||||
std::vector<Client*> client_append_list_;
|
||||
Mutex client_lock_; //客户端列表锁给append_list用
|
||||
std::map<uint16_t, Client*> client_list_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user