游戏服务器之逻辑网关(在逻辑服务器中)

本文探讨了游戏服务器中的逻辑网关设计,包括配置可变的逻辑网关数量及四大线程:接收连接线程负责新建会话,数据发送线程多线程发送消息,数据接收线程处理网络数据,数据处理线程执行连包、校验和消息派发。各线程协同工作,确保游戏服务器稳定运行。
摘要由CSDN通过智能技术生成

本文要说的是游戏服务器之逻辑网关,在单进程的逻辑服务器中存在多个逻辑网关。


设计上:

(1)逻辑网关个数是配置的

(2)每个逻辑网关就包含四类线程:

1)网关接收连接线程:循环检查连接并建立新会话

2)网关的数据发送线程(配置多个):发送消息发送队列的数据,每个发送线程处理该线程的,多线程发送

3)网关的数据接收线程:网络接收数据到数据包接收队列

4)网关的数据处理线程: 处理连包,校验,派送到账号线程(登录消息)或逻辑线程(系统消息)

 

 


1、网关接收连接线程

接收连接和创建会话


网关接收连接循环不断地检查新连接的接收

void *CSelectRunSockProcesser::AcceptThreadRoutine(CSelectRunSockProcesser *pRunSock)
{
while ( !pRunSock->m_boStoping )
{
pRunSock->NewSession();
}
ExitThread( 0 );
}


检查建立新的会话(这里是select模型检查)

VOID ExecSockMgr::NewSession()
{
SOCKET nSocket;
SOCKADDRIN sRemote;
int nErr;
socklen_t nRemoteSize;
u_long uBlock;
PRUNGATEUSERSESSION pSession;

fd_set readfds, errfds;
timeval tv;

FD_ZERO( &readfds );
FD_ZERO( &errfds );
FD_SET( m_ListenSocket, &readfds );
tv.tv_sec = 1;
tv.tv_usec = 0;
//检查是否有接入的socket
nErr = select( int(m_ListenSocket+1), &readfds, NULL, &errfds, &tv );
if ( nErr < 0 || FD_ISSET(m_ListenSocket, &errfds) )
{
SocklogError( __FUNCTION__, "select", WSAGetLastError() );
return;
}
if ( nErr == 0 || !FD_ISSET(m_ListenSocket, &readfds) )
{
return;
}
if ( m_boStoping )
{
return;
}

nRemoteSize = sizeof(sRemote);
nSocket = accept( m_ListenSocket, (sockaddr*)&sRemote, &nRemoteSize );
if ( nSocket == INVALID_SOCKET )
{
SocklogError( __FUNCTION__, "accept", WSAGetLastError() );
return;
}

//用户队列满后一段时间内不接受新连接
if ( GetTickCount() < m_SessionFullTick )
{
closesocket( nSocket );
return;
}

uBlock = 1;
//设置非阻塞
 
int nFlag = fcntl(nSocket, F_GETFL, 0);
if(0 > nFlag)
{
closesocket(nSocket);
SocklogError( __FUNCTION__, "fcntl", errno );
}
if (fcntl(nSocket, F_SETFL, nFlag|O_NONBLOCK) < 0)
{
closesocket(nSocket);
SocklogError( __FUNCTION__, "fcntl", errno );
}
  
if ( !(pSession = m_pExecSockDataMgr->NewSession( nSocket, sRemote )) )
{
closesocket( nSocket );
SocklogError( __FUNCTION__, "用户队列已经满了。", ERROR_SUCCESS );
m_SessionFullTick = GetTickCount() + 10 * 1000;
return;
}

// AdjustSocketSendBufSize( nSocket, 32 * 1024 );
}

建立新的会话并添加会话列表
PRUNGATEUSERSESSION ExecSockDataMgr::NewSession(SOCKET nSocket, SOCKADDRIN RemoteAddr)
{
PRUNGATEUSERSESSION pNewSession = NULL;

EnterCriticalSection( &m_SessionLock );
pNewSession = m_SessionAllocator.allocObject();//会话分配器
pNewSession->nSocket = INVALID_SOCKET;
pNewSession->SendBuf.nOffset = 0;
pNewSession->dwCloseTick = 0;
pNewSession->boMarkToClose = false;
pNewSession->boRemoteClosed = false;


PRUNGATEUSERSESSION *pSessionList = m_SessionList;
for (INT_PTR i=m_SessionList.count()-1; i>-1; --i)
{
if (!pSessionList[i])
{
pSessionList[i] = pNewSession;
pNewSession->nIndex = (int)i;
pSessionList = NULL;
break;
}
}
if (pSessionList)//找不到空闲的位置,就添加到最后面,需要拓展列表的长度
{
pNewSession->nIndex = (int)m_SessionList.add(pNewSession);
}
LeaveCriticalSection( &m_SessionLock );


if ( pNewSession )//内存地址可能改变
{
pNewSession->SockAddr= RemoteAddr;
pNewSession->nPlayerIndex= -1;
pNewSession->pPlayer= NULL;
pNewSession->wPacketVerifyKey= 0;
pNewSession->nRecvPacketCount=0;
pNewSession->nSendPacketCount=0;
pNewSession->btUserState= eGUSWaitRequestKey;/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值