依据传奇游戏服务器源码总结了一下服务器开发中比较关心的一些问题。
(1)线程之间的共享数据如何同步
CIntLock封装了临界区管理,包含了Lock()和Unlock()两个操作函数,所有
需要同步的类都从CIntLock派生,例如:CWHQueue,CDBManager,CGlobalUserList,CUserInfo,CPlayerObject
(2)数据库是如何管理和连接的
数据库服务器DBSvr采用ODBC进行数据库连接,CConnection,CDatabase,CRecordset,CDBManager等类实现对数据库的管理,这几个类
对ODBC SDK进行了封装。
DBSvr.cpp:数据库连接采用一次连接多次使用的方式,在应用程序初始化函数InitInstance中,
GetDBManager()->Init( InsertLogMsg, szDatabase, "sa", "prg" );
进行数据库的连接。
(3)玩家处理线程ProcessUserHuman主要完成什么工作
GameSvr\ProcessUserHuman.cpp
ProcessUserHuman线程主要负责处理玩家的游戏动作以及数据的发送
pUserInfo->Operate();// 执行玩家游戏动作
pGateInfo->xSend();// 发送数据
(4)数据如何发送
在AcceptEx接受连接后,将套接字发送缓冲设置为0,
int zero = 0;
setsockopt(pGateInfo->sock, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero) );
需要发送的数据通过m_pUserInfo->m_pGateInfo->m_xSendBuffQ.PushQ((BYTE *)lpSendBuff);
放入发送队列。由ProcessUserHuman线程中循环调用pGateInfo->xSend();进行发送。
因为发送缓冲已设置为0,那么接下去在pGateInfo->xSend()中调用WSASend将被阻塞,ProcessUserHuman线程中调用所有pGateInfo的xSend(), 数据将被顺序发送出去。
(5)CGateInfo有什么作用,对象是在哪里分配的
CGateInfo用于管理数据收发,包含于CUserInfo对象中。
GameSvr\SockMsg_GateComm.cpp
AcceptThread中分配CGateInfo对象,并加入到全局列表中
CGateInfo* pGateInfo = new CGateInfo;
if (pGateInfo)
{
pGateInfo->m_sock = Accept;
CreateIoCompletionPort((HANDLE)pGateInfo->m_sock, g_hIOCP, (DWORD)pGateInfo, 0);
if (g_xGateList.AddNewNode(pGateInfo))
......
(6)CUserInfo有什么作用,对象在哪里分配
CUserInfo是非常重要的一个类,用于管理玩家信息,包含了
CPlayerObject* m_pxPlayerObject;
CGateInfo* m_pGateInfo;
Operate();
等重要变量与函数。
对于GameSvr:
GameSvr\GateInfo.cpp
CGateInfo::OpenNewUser中,
取出g_xUserInfoArr中空闲的CUserInfo对象加入到g_xLoginOutUserInfo列表中,然后对pUserInfo进行赋值
pUserInfo->Lock();
pUserInfo->m_sock = lpMsgHeader->nSocket;
pUserInfo->m_pxPlayerObject = NULL;
pUserInfo->m_pGateInfo = this;
pUserInfo->Unlock();
对于LoginSvr:
CGateInfo有个变量CWHList<CUserInfo*> xUserInfoList;
CGateInfo::ReceiveOpenUser中分配CUserInfo对象,xUserInfoList.AddNewNode加入到xUserInfoList列表中
GameSvr与LoginSvr分配CUserInfo对象的方式的不同,其根本原因在于LoginSvr只在登录过程中使用CUserInfo,
不像GameSvr一样需要在整个游戏中时间使用CUserInfo对象。
(7)在何处投递收数据操作
GameSvr\SockMsg_GateComm.cpp
在AcceptThread线程中,接受一个连接后,pGateInfo->Recv();投递异步收数据操作
收缓冲位于:pGateInfo->OverlappedEx[0]中
工作线程ServerWorkerThread中,在收到数据并处理完成后继续投递异步收数据操作
(8)收数据完成后的处理
GameSvr\SockMsg_GateComm.cpp
工作线程ServerWorkerThread中,
if (lpOverlapped->nOvFlag == OVERLAPPED_RECV)
{
....
// 修改缓冲区数据实体的大小
pGateInfo->OverlappedEx[0].bufLen += dwBytesTransferred;
// 循环判断是不是完整的包
while ( pGateInfo->HasCompletionPacket() )
{
// 解包操作...
(9)判断是否收到了完整的包
CGateInfo::HasCompletionPacket中,缓冲区收到的数据长度>=包头固定长度+包头中指明的数据区长度,就
认为收到了完整的包。
(10)如何进行解包操作
char * CGateInfo::ExtractPacket( char *pPacket )
{
// 包大小=包头大小+数据区大小
int packetLen = sizeof( _TMSGHEADER ) + ((_LPTMSGHEADER) &OverlappedEx[0].Buffer)->nLength;
// 把完整的包复制到pPacket中
memcpy( pPacket, OverlappedEx[0].Buffer, packetLen );
// 把完整的包后面的数据移到缓冲区头部(解决粘包的问题)
memmove( OverlappedEx[0].Buffer, OverlappedEx[0].Buffer + packetLen, DATA_BUFSIZE - packetLen );
// 修改缓冲区数据大小
OverlappedEx[0].bufLen -= packetLen;
return pPacket + packetLen;
}
(11)如何处理玩家游戏数据
在ServerWorkerThread中解包操作完成后,如果数据类型是GM_DATA类型,调用pUserInfo->ProcessUserMessage
处理玩家游戏数据,调用m_pxPlayerObject->AddProcess,在AddProcess中分配PROCESSMSG对象,并将数据复制到
该对象中,然后Push到m_ProcessQ队列中待处理。ProcessUserHuman线程中遍历列表中的所有用户,调用
pUserInfo->Operate(),在CPlayerObject::Operate中从m_ProcessQ中Pop出游戏动作进行处理。
分享到:
相关推荐
资料文件用于解决C#编程中发生的粘包问题的处理
使用多线程接受消息和发送消息分开的思想,保证了程序内置自动消息处理过程,做到消息可靠高并发的效果
由于在开发的过程中,遇到线程阻塞导致...可以对socket通信、串口通信等进行粘包处理,已实践验证。 但是你需要根据你的通讯协议来修改一些参数,比如包长是在第几个字节上的。需要根据协议修改的地方 已在代码里备注。
带粘包处理的ScktComp Sin Example Rar
Unity socket 案例包含粘包处理
netty 数据分包、组包、粘包处理机制(部分)1
本demo演示了 多个json包粘在一起的处理方法,用到了第三方库 QDAC
当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API)。TCP/IP传输层有两个并列的协议:TCP和UDP。其中TCP(transport control protocol,传输控制协议)是面向连接的,提供高...
netty案例,netty4.1基础入门篇八《NettyClient半包粘包处理、编码解码处理、收发数据方式》源码 ...
TCP粘包的一种解决方法,使用见使用示例。
Mina断包,粘包的处理。(完整实例,客户端,服务端)
在原有的资源会出现粘包现象。因socket消息是#开头$结束的。当发多个连续消息时,会出现粘包现象,此时进行处理。主要处理FormClient.cs对接收事件粘包时进行分割处理
C#解决socket通信过程中粘包分包问题,本项目是一个只有6个C#代码文件的开源小工程,用来学习基于TCP的套接字通信包,可以自定义通信协议,处理分包和粘包,内置一个服务端和客户端的套接字程序,也有测试代码和对应...
主要为大家详细介绍了C#中TCP粘包问题的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
。。。
主要介绍了使用Netty解决TCP粘包和拆包问题过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
本demo模拟了TCP通信中发送端和接收端的行为,并利用序列化和反序列化的思想,自定义协议来解决TCP的粘包和拆包问题。
C语言的json解析,主要用于处理粘包; 将连续的多包json数据拆解成json链表~
主要介绍了C# Socket粘包处理讲解,大家可以参考使用