This commit is contained in:
aixianling
2025-01-09 17:45:40 +08:00
commit 5c9f1dae4a
3482 changed files with 1146531 additions and 0 deletions

View File

@@ -0,0 +1,235 @@
#include "StdAfx.h"
#include <map>
#include "client/client_obj_mgr.h"
#include "event/select_event.h"
#include "event/epoll_event.h"
GameClientMgr::GameClientMgr(const char *name, GateServer *srv) {
srv_ = srv;
gw_cli_ = new GameWorldClient(srv, this, name);
cli_obj_mgr_ = new ClientObjMgr();
inner_msg_list_.setLock(&inner_msg_lock_);
#if USE_EPOLL
event_ = new EpollEvent(this);
#else
event_ = new SelectEvent(this);
#endif
}
GameClientMgr::~GameClientMgr() {
cli_obj_mgr_->flush();
SafeDelete(cli_obj_mgr_);
inner_msg_list_.flush();
inner_msg_list_.clear();
SafeDelete(gw_cli_);
}
void GameClientMgr::SetMaxSession(int max_session) {
cli_obj_mgr_->SetMaxSession(max_session);
}
void GameClientMgr::InitGameWorldClient(const char * ip, int port) {
gw_cli_ = new GameWorldClient(srv_, this, GetServiceName());
gw_cli_->UseBaseAlloc(true);
gw_cli_->SetHost(ip);
gw_cli_->SetPort(port);
}
bool GameClientMgr::onConnect(SOCKET nSocket, sockaddr_in * pAddrIn) {
if (!gw_cli_->connected()) return false;
Client *cli = new Client(this, nSocket, pAddrIn);
cli_obj_mgr_->setNewClient(cli);
cli_obj_mgr_->flush();
cli->SetBlockMode(false);
GateInterMsg msg;
msg.msg_id_ = gcAddClient;
msg.data_.fd_ = nSocket;
msg.data_.sessidx_ = cli->GetSessionId();
PostMsg(msg);
OutputMsg(rmTip, _T("[Login] (1) 客户端连接上来: gatekey(%d)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
cli->GetSKey(), nSocket, cli->GetNetId().index_, cli->GetNetId().gate_id_, GetCurrentThreadId());
//MSG_TIP("new client connect fd:%d, sid:%d", cli->GetFd(), cli->GetSessionId());
return true;
}
int GameClientMgr::Run() {
inner_msg_list_.flush();
int count = inner_msg_list_.count();
for (int i = 0; i < count; ++i)
{
GateInterMsg& msg = inner_msg_list_[i];
OnRecvSysMsg(msg);
}
inner_msg_list_.clear();
event_->RunOne();
return count;
}
void GameClientMgr::OnStart() {
MSG_LOG("GameClientMgr::OnStart");
event_->init();
}
void GameClientMgr::OnStop() {
MSG_LOG("GameClientMgr::OnStop");
}
void GameClientMgr::Stop() {
MSG_LOG("%s, start", GetServiceName());
while (gw_cli_->GetPacketCount()) {//这里还有包没发完,导致一致没法停止
gw_cli_->SingleRun();
Sleep(1);
}
gw_cli_->Stop();
Inherited::Stop();
MSG_LOG("%s, ok", GetServiceName());
}
void GameClientMgr::OnRecvSysMsg(GateInterMsg & msg)
{
switch (msg.msg_id_)
{
case gcAddClient:
{
event_->AddReadFd(msg.data_.fd_, cli_obj_mgr_->get(msg.data_.sessidx_));
break;
}
case gcServerIdx:
{
Client* cli = cli_obj_mgr_->get(msg.data_.idx_);
if (cli) {
cli->GetNetId().gate_id_ = msg.data_.para_;
OutputMsg(rmTip, _T("[Login] (5) LogicServer已成功添加玩家Gate gatekey(%d)socket(%lld)GateIdx(%d)LogicIdx(%d)CurrentThreadId(%d)。"),
cli->GetSKey(), cli->GetNetId().socket_, cli->GetNetId().index_, cli->GetNetId().gate_id_, GetCurrentThreadId());
}
break;
}
case gcGWData:
{
Client* cli = cli_obj_mgr_->get(msg.data_.index_);
if (cli) {
auto dp = msg.data_.packet_;
cli->OnGameWorldRecv(dp->getOffsetPtr(), dp->getAvaliableLength());
}
gw_cli_->FreeBackUserDataPacket(msg.data_.packet_);
break;
}
case gcGWClose:
{
Client* cli = cli_obj_mgr_->get(msg.data_.index_);
if (cli) {
cli->Close();
}
break;
}
case gcChAdd:
{
uint64_t key = MAKEINT64(msg.data_.channel_, msg.data_.para_);
channel_indexs_map_[key].insert(msg.data_.idx_);
break;
}
case gcChDel:
{
uint64_t key = MAKEINT64(msg.data_.channel_, msg.data_.para_);
channel_indexs_map_[key].erase(msg.data_.idx_);
break;
}
case gcChBro:
{
uint64_t key = MAKEINT64(msg.data_.b_channel_, msg.data_.b_para_);
auto &list = channel_indexs_map_[key];
for (auto idx:list) {
Client* cli = cli_obj_mgr_->get(idx);
if (cli) {
auto dp = msg.data_.packet_;
cli->OnGameWorldRecv(dp->getOffsetPtr(), dp->getAvaliableLength());
}
}
gw_cli_->FreeBackUserDataPacket(msg.data_.dp_);
break;
}
case gcGWDisconn:
{
CloseAllClient();
break;
}
}
}
void GameClientMgr::ProssClient(void) {
//cli_obj_mgr_->flush();
auto &list = cli_obj_mgr_->getClientMap();
std::vector<uint16_t> remove_list;
for (auto it:list) {
Client *cli = it.second;
if(cli)
{
if (cli->IsClose()) {
remove_list.push_back(cli->GetSessionId());
continue;
}
cli->RecvData();
cli->PacketHandle();
cli->WriteEvent();
cli->SendData();
}
}
for (auto idx: remove_list) {
Client *cli = cli_obj_mgr_->remove(idx);
SafeDelete(cli);
}
remove_list.clear();
}
void GameClientMgr::HandleReadEvent(SOCKET fd, Client * cli) {
if (cli) {
cli->RecvData();
cli->PacketHandle();
event_->AddWriteFd(fd, cli);
}
}
void GameClientMgr::HandleWriteEvent(SOCKET fd, Client * cli) {
if (cli) {
cli->WriteEvent();
if (!cli->SendData()) {
event_->AddWriteFd(fd, cli);
}
}
}
void GameClientMgr::CloseAllClient() {
cli_obj_mgr_->flush();
auto &list = cli_obj_mgr_->getClientMap();
std::vector<uint16_t> remove_list;
for (auto it : list) {
Client *cli = it.second;
cli->Close();
}
}
void GameClientMgr::HaveData(Client * cli) {
if(cli) {
event_->AddWriteFd(cli->GetFd(), cli);
}
}
void GameClientMgr::CloseClient(Client * cli) {
event_->DelFd(cli->GetFd());
closesocket(cli->GetFd());
if (cli_obj_mgr_->get(cli->GetSessionId()))
{
cli_obj_mgr_->remove(cli->GetSessionId());
}
}
bool GameClientMgr::Startup() {
if (!Inherited::Startup()) {
return false;
}
// 创建发送线程
return gw_cli_->Startup();
}

View File

@@ -0,0 +1,95 @@
#pragma once
#include <map>
#include <set>
typedef union GateInterMsgData {
struct {
uint32_t b_channel_;
uint32_t b_para_;
DataPacket* dp_;
};
struct {
uint32_t index_;
DataPacket* packet_;
};
struct {
uint32_t idx_;
uint32_t para_;
uint32_t channel_;
};
struct {
uint32_t sessidx_;
SOCKET fd_;
};
} tagGateInterMsgData;
typedef struct GateInterMsg
{
int msg_id_;
GateInterMsgData data_;
} tagGateInterMsg;
class GameWorldClient;
class BaseEvent;
class SocketSrv;
class ClientObjMgr;
enum {
gcAddClient = 1, //增加一个新的客户端连接
gcGWData = 2, //游戏服给客户端发消息
gcGWClose = 3, //游戏服主动关闭客户端
gcChBro = 4,//频道广播消息
gcChAdd = 5,//频道信息增加
gcChDel = 6,//频道信息删除
gcGWDisconn = 7,//游戏服断开连接
gcServerIdx = 8,//游戏服的玩家对应gateid
};
class GameClientMgr : public SocketSrv {
public:
typedef SocketSrv Inherited;
GameClientMgr(const char *name, GateServer *srv);
~GameClientMgr();
void SetMaxSession(int max_session);
bool Startup();
void InitGameWorldClient(const char *ip, int port);
GameWorldClient* GetGameWorldClient(void) { return gw_cli_; }
virtual bool onConnect(SOCKET nSocket, sockaddr_in* pAddrIn);
//单次逻辑处理
virtual int Run();
virtual void OnStart();
virtual void OnStop();
virtual void Stop();
void PostMsg(GateInterMsg& msg) {
inner_msg_list_.append(msg);
}
void OnRecvSysMsg(GateInterMsg& msg);
//select模式使用
void ProssClient(void);
//epoll模式使用
void HandleReadEvent(SOCKET fd, Client* cli);
void HandleWriteEvent(SOCKET fd, Client* cli);
//断开所有客户端连接
void CloseAllClient();
void HaveData(Client* cli);
void CloseClient(Client *cli);
protected:
GateServer *srv_;
GameWorldClient *gw_cli_;
ClientObjMgr *cli_obj_mgr_;
std::map<uint64_t, std::set<int> > channel_indexs_map_;
QueueList<GateInterMsg> inner_msg_list_;//内部消息列表
Mutex inner_msg_lock_;//内部消息列表锁
BaseEvent *event_;//事件处理
};

View File

@@ -0,0 +1,148 @@
#ifdef _MSC_VER
#include <Windows.h>
#include <process.h>
#else
#include <pthread.h>
#endif
#include "StdAfx.h"
#include "socket_srv.h"
SocketSrv::SocketSrv() {
srv_stoped_ = true;
memset(server_name_, 0, sizeof(server_name_));
#ifdef _MSC_VER
accept_thread_ = NULL;
#else
accept_thread_ = 0;
#endif
accept_exit_ = true;
}
SocketSrv::~SocketSrv()
{
#ifdef _MSC_VER
if (NULL != accept_thread_) {
CloseHandle(accept_thread_);
}
accept_thread_ = NULL;
#else
accept_thread_ = 0;
#endif
}
#ifdef _MSC_VER
void STDCALL SocketSrv::ServerSocketAcceptThreadRoutine(void* arg) {
#else
void * SocketSrv::ServerSocketAcceptThreadRoutine(void * arg) {
#endif
SocketSrv *srv = (SocketSrv*)arg;
struct sockaddr_in server_addr;
SOCKET listen_fd_ = 0;
if ((listen_fd_ = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) {
MSG_ERR("create socket error:%d",errno);
assert(false);
}
#ifdef _MSC_VER
char optval = 1;
#else
int optval = 1;
#endif
if (setsockopt(listen_fd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == SOCKET_ERROR) {
MSG_ERR("setsockopt");
assert(false);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(srv->GetServicePort());
server_addr.sin_addr.s_addr = inet_addr(srv->GetServiceHost());
memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero));
if (::bind(listen_fd_, (struct sockaddr *)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
MSG_ERR("bind error");
assert(false);
}
if (listen(listen_fd_, 5) == SOCKET_ERROR) {
MSG_ERR("listen error");
assert(false);
}
socklen_t len = sizeof(sockaddr);
do {
sockaddr_in cli_addr;
SOCKET nSocket = accept(listen_fd_, (sockaddr*)&cli_addr, &len);
if (srv->Started() && !srv->onConnect(nSocket, &cli_addr)) {
closesocket(nSocket);
}
} while (srv->Started());
closesocket(listen_fd_);
srv->accept_exit_ = true;
#ifdef _MSC_VER
ExitThread(0);//设置线程退出返回值
#else
return NULL;
#endif
}
void SocketSrv::SetServiceName(const char * sName)
{
_STRNCPY_A(server_name_, sName);
}
void SocketSrv::SetServiceHost(const char * sHost)
{
_STRNCPY_A(host_, sHost);
}
void SocketSrv::SetServicePort(const int nPort) {
port_ = nPort;
}
bool SocketSrv::Startup() {
Inherited:Start();
bool ret = true;
int err = 0;
srv_stoped_ = false;
#ifdef _MSC_VER
accept_thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ServerSocketAcceptThreadRoutine, this, 0, NULL);
if (!accept_thread_) {
err = GetLastError();
ret = false;
}
#else
if (pthread_create(&accept_thread_, NULL, ServerSocketAcceptThreadRoutine, this)) {
err = errno;
ret = false;
}
#endif
if (!ret) {
MSG_ERR("create listen thread error %d", err);
return false;
}
accept_exit_ = false;
return true;
}
void SocketSrv::Stop() {
if (srv_stoped_) return;
MSG_LOG("start");
srv_stoped_ = true;
// while (!accept_exit_) {
// Sleep(1);
// }
//#ifdef _MSC_VER
// CloseThread(accept_thread_);
//#endif
Inherited::Stop();
MSG_LOG("ok");
}
void SocketSrv::OnRoutine() {
OnStart();
while (!terminated()) {
if (Run() <= 0)
Sleep(1);
}
OnStop();
}

View File

@@ -0,0 +1,55 @@
#pragma once
class SocketSrv : public thread::BaseThread {
public:
typedef thread::BaseThread Inherited;
SocketSrv();
~SocketSrv();
#ifdef _MSC_VER
static void STDCALL ServerSocketAcceptThreadRoutine(void* srv);
#else
static void* ServerSocketAcceptThreadRoutine(void* arg);
#endif
virtual bool onConnect(SOCKET nSocket, sockaddr_in* pAddrIn) = 0;
virtual void OnRoutine();
//单次逻辑处理
virtual int Run() = 0;
virtual void OnStart() = 0;
virtual void OnStop() = 0;
inline const char* GetServiceName()
{
return server_name_;
}
inline const char* GetServiceHost()
{
return host_;
}
inline int GetServicePort()
{
return port_;
}
inline bool Started()
{
return !srv_stoped_;
}
void SetServiceName(const char* sName);
void SetServiceHost(const char* sHost);
void SetServicePort(const int nPort);
bool Startup();
virtual void Stop();
private:
#ifdef _MSC_VER
HANDLE accept_thread_; //接受客户端连接线程
#else
pthread_t accept_thread_;
#endif
bool srv_stoped_; //是否停止工作线程
bool accept_exit_; //监听线程完整退出
char server_name_[256]; //服务名称
char host_[256]; //服务绑定地址
int port_; //服务绑定端口
};