我想知道如何使用RakNet将数据包发送到客户端 - 服务器架构中的客户端。在这个sample code中我们有这一行:
peer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
但是,原型如下(来自接口类):
virtual uint32_t Send( const RakNet::BitStream * bitStream,
PacketPriority priority,
PacketReliability reliability,
char orderingChannel,
const AddressOrGUID systemIdentifier,
bool broadcast,
uint32_t forceReceiptNumber=0 )=0;
如您所见,第5个参数采用AddressOrGUID,这意味着我们可以像样本一样发送SystemAddress,但也可以发送连接机器的唯一GUID。
有一个名为:
的功能RakNet::GetSystemAddressFromGUID();
但是我不确定RakNet是否使用它来转换我们可以作为参数发送的GUID(我没有在RakPeer(RakPeerInterface的实现)和I'中找到任何使用此方法的方法。我无法找到每个tick发送缓冲数据包的方式。)
问题如下:
示例代码直接回复收到的数据包。但是,在游戏中,服务器必须在不从客户端接收数据包的情况下发送信息。所以我无法访问类似
的内容packet->systemAddress
因为没有收到数据包。
所以我必须在我的Player类中存储一些内容,以了解如何向它们发送数据包:SystemAddress或RakNetGUID。 RakNetGUID比SystemAddress更简单,更轻便。
但是,如果RakNet使用GetSystemAddressFromGUID(),它就不值得,因为它有一个O(log(n))算法。
我是否需要自己为每个播放器存储SystemAddress,或者RakNet :: Send()是否不将此方法与RakNetGUID一起使用?
谢谢!
答案 0 :(得分:0)
好的,我第一次尝试理解源代码时没有正确地遵循条件语句,这是错误的,因为这个问题非常具体,我认为查看源代码会很棒。
简单的答案是是,将RakNetGUID存储在播放器类中
详细信息:
好的,首先,有关的文件只是RakPeer.cpp。起点是:
uint32_t RakPeer::Send( const RakNet::BitStream * bitStream,
PacketPriority priority,
PacketReliability reliability,
char orderingChannel,
const AddressOrGUID systemIdentifier,
bool broadcast,
uint32_t forceReceiptNumber ) // Line 1366
然后,我们有一行调用SendBuffered:
SendBuffered((const char*)bitStream->GetData(),
bitStream->GetNumberOfBitsUsed(),
priority,
reliability,
orderingChannel,
systemIdentifier, // This is the initial AddressOrGUID
broadcast,
RemoteSystemStruct::NO_ACTION,
usedSendReceipt); // Line 1408
在上面的方法中,我们可以知道缓冲区变量的名称:
bufferedCommands.Push(bcs); // Line 4216
通过搜索每个使用bufferedCommands的地方,我们找到了一个有意义的方法名称:
bool RakPeer::RunUpdateCycle(BitStream &updateBitStream ) // Line 5567
我们可以在这里找到一个发送每个缓冲消息的循环:
callerDataAllocationUsed=SendImmediate((char*)bcs->data,
bcs->numberOfBitsToSend,
bcs->priority,
bcs->reliability,
bcs->orderingChannel,
bcs->systemIdentifier, // Initial AddressOfGUID
bcs->broadcast,
true,
timeNS,
bcs->receipt); // Line 5630
RakPeer :: SendImmediate()会要求RakPeer :: GetSystemIndexFromGuid()找到合适的索引:
else if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
remoteSystemIndex=GetSystemIndexFromGuid(systemIdentifier.rakNetGuid); // Line 4300
最后,最后一个方法会在找到时将索引直接存储在RakNet :: RakNetGUID中:
unsigned int i;
for ( i = 0; i < maximumNumberOfPeers; i++ )
{
if (remoteSystemList[ i ].guid == input )
{
// Set the systemIndex so future lookups will be fast
remoteSystemList[i].guid.systemIndex = (SystemIndex) i;
return i;
}
} // Line 2440
如果我们用RakNetGUID调用Send(),那么它将检查是否设置了RakNetGUID :: systemIndex。如果是,则不需要搜索。否则,对于发送的第一个数据包,它将具有线性搜索时间O(n)(n = maximumNumbersOfPeers)。
我写这篇文章是为了帮助人们了解它是如何工作的,如果他们有同样的问题。
答案 1 :(得分:0)
从文档中:http://www.raknet.net/raknet/manual/systemaddresses.html
优选的是,你通过RakNetGUID指远程系统,代替SystemAddress。 RakNetGUID为RakPeer的一个实例的唯一标识符,而SystemAddress不是。而且,有必要专门使用RakNetGUID如果你打算使用路由器2的插件。
SystemAddress仅仅是IP和端口的组合