游戏服务器之多线程的会话管理

本文探讨了游戏服务器中逻辑网关的会话管理,涉及主线程的会话列表初始化与销毁,监听线程创建会话,接收线程关闭错误会话等。重点在于多线程环境下如何有效地管理和维护会话,确保数据的安全发送和接收。
摘要由CSDN通过智能技术生成

游戏服务器的逻辑服务器下有逻辑网关(逻辑网关可有多个),逻辑网关下有一个监听线程、一个接收线程、一个接收处理线程和多个发送线程。

所以,主线程、监听线程、接收线程、接收处理线程、发送线程之间需要对会话的数据进行管理。


设计上:

(1)在主线程的所有的网关对象管理会话列表的初始化和销毁,在启动网关时会初始化。

(2)监听线程监听到新的连接会创建会话(分配发送缓冲区和接收缓冲区),并添加到会话列表。

(3)接收数据处理线程遍历会话列表,标识关闭长时间(10min)不活动的会话。对于被标识关闭(可能在别的线程标识的)的会话需要释放会话的资源(接收缓冲区和发送缓冲区),并且置空该会话在会话列表中的位置(以便以后放置新的会话)。

(4)发送线程关闭发送错误的会话(并标识关闭),关闭发送包过大(4MB)的会话。

(5)接收线程关闭接收出错的会话(以及标记关闭的会话)。



1、网关会话列表初始化和销毁(主线程)

(1)网关启动初始化会话列表

初始化会话队列

BOOL ExecSockDataMgr::Start()
{
......
//初始化会话队列
InitSessions();
......

}

VOID ExecSockDataMgr::InitSessions()
{
EnterCriticalSection( &m_SessionLock );
m_SessionList.reserve(65536);
LeaveCriticalSection( &m_SessionLock );
}

(2)网关关闭,关闭所有的会话

关闭和销毁会话列表里的所有的会话,回收其内存

VOID ExecSockDataMgr::Stop()
{
	......
	CancelRemainSendSessionBuffers();
	CloseAllSessions( TRUE );//关闭所有的会话
	UninitSessions();//释放所有的会话
	m_boStarted = FALSE;
}


释放该网关中所有的会话

VOID ExecSockDataMgr::UninitSessions()
{
	EnterCriticalSection( &m_SessionLock );
	
	PRUNGATEUSERSESSION *pSessionList = m_SessionList;
	PRUNGATEUSERSESSION pSession;
	for (INT_PTR i=m_SessionList.count()-1; i>-1; --i)
	{
		pSession = pSessionList[i];
		if (pSession)
		{
			FreeSession(pSession);
		}
	}
	m_SessionList.clear();
	m_SessionAllocator.freeAll();
	LeaveCriticalSection( &m_SessionLock );
}



关闭所有的会话

VOID ExecSockDataMgr::CloseAllSessions(BOOL boForceClose)
{
	INT_PTR i;
	TICKCOUNT dwCurTick;
	PRUNGATEUSERSESSION pSession;
	
	EnterCriticalSection( &m_SessionLock );//会话锁
	EnterCriticalSection( &m_RecvQueueLock );//接收队列锁(单个网关内接受数据线程有一个)
	for ( i=0; i<m_nSendThreadCount; ++i )
	{
		EnterCriticalSection( &m_SendThreads[i].SendQueueLock );// 发送队列锁(单个网关内发送线程有多个)
	}
	moon::OS::osSleep(3);//休眠以等待数据接收以及各发送线程被阻塞
	
	dwCurTick = _getTickCount();
	for ( i=m_SessionList.count()-1; i>-1; --i )
	{
		pSession = m_SessionList[i];
		if ( pSession && pSession->nSocket != INVALID_SOCKET )
		{
			if ( boForceClose )
			{
				m_SessionList[i] = NULL;
				
				PostEngineClosePlayer( pSession );
				closesocket( pSession->nSocket );
				pSession->boMarkToClose = true;
				pSession->boRemoteClosed = true;
				pSession->dwCloseTick = 0;
				pSession->nSocket = INVALID_SOCKET;
				pSession->nVerifyIdx = 0;
				FreeSession(pSession);
			}
			else CloseSession( pSession );//关闭会话(关闭socket和标识关闭会话)
			
		}
	}
	
	
	for ( i=0; i<m_nSendThreadCount; ++i )
	{
		LeaveCriticalSection( &m_SendThreads[i].SendQueueLock );
	}
	LeaveCriticalSection( &m_RecvQueueLock );
	LeaveCriticalSection( &m_SessionLock );
}


2、创建会话(监听线程)

添加会话到会话列表

PRUNGATEUSERSESSION ExecSockDataMgr::NewSession(SOCKET nSocket, SOCKADDRIN RemoteAddr)
{
	PRUNGATEUSERSESSION
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值