在网络环境的游戏应用中,由于NAT以及INTERNET的关系,必须有一个masterserver来做中转
如果说语意的话,实现的是Corba的Naming service,只不过这个是基于udp的.
用udp实现上在基础层面简单,但是在业务逻辑上会比较麻烦,因为还会遇到udp包大小的限制的自己手动来写逻辑检测以及
其本质是单方向的无连接的通信.连接靠双端自己的能交流的同类的实例化对象来维持.
但是这个,没有办法,效率为先.所幸其中已经封装好的
tnl 概念很好.rpc之后根本就没有什么执行代码
全都是 在client server之间 联结上了
一个 rpc 到 一个 rpc 再到一个rpc
所以 咋一看会蒙 不知道逻辑执行在哪里
可以说是全自动 就一开始 InitRequest 物理连接上的时候要显式的传递一下
bitstream里的数据 ,以后就自动化了
其实也是用宏也需要自己去 care packet size和rpc之间的 logic但是毕竟方便多了
然后所有都统一在interface->processConnections把包发了出去, interface(可以是继承特例化了的)
把所有的 connection 都做了
并且不是自己去 裸连的
conn->connectArranged(getInterface(), fullPossibleAddresses,
nonce, serverNonce, theSharedData,false);
masterclient 的main.cpp 的 325行
在masterclient 的main.cpp 的245行
// Invalidate the query...
mCurrentQueryId++;
你能看到一个 query 是 业务逻辑自己维护的
query id 自增就是表明一次业务作完了 连接再次开始
没有底层帮忙其实也是很裸的
以下是对masterclient 里的 .cpp的代码的摘录:
MasterServerConnection
GameConnection
两个socket 两个 connection 非阻塞I/O
class GameConnection : public EventConnection
class MasterServerConnection : public MasterServerInterface
只是实现自己所需要的那部分的stub.至于不需要的都是 {}这样的而已
到了master那边master自己再继承实现,然后再以下
TNL_IMPLEMENT_NETCONNECTION(MasterServerConnection, NetClassGroupMaster, true);
用这种hook 来使 Interface 来调用自己
TNL_DECLARE_RPC_OVERRIDE(m2cQueryGameTypesResponse, (U32 queryId, Vector<StringTableEntry> gameTypes, Vector<StringTableEntry> missionTypes))
{
// Ignore old queries...
if(queryId != mCurrentQueryId)
return;
使用逻辑上的Id来维持一个连接
// when we receive the final list of mission and game types,
// query for servers:
if(gameTypes.size() == 0 && missionTypes.size() == 0)
{
// Invalidate old queries
mCurrentQueryId++;
mIPList.clear();
// And automatically do a server query as well - you may not want to do things
// in this order in your own clients.
c2mQueryServers(mCurrentQueryId, 0xFFFFFFFF, 0, 128, 0, 128, 0, "", "");
}
自己自增一个ID上的完成,清空在连接时候所用的资源
conn->connectArranged(getInterface(), fullPossibleAddresses,
nonce, serverNonce, theSharedData,false);