简体   繁体   English

使用RakNet发送数据包的最佳方法

[英]Best way to send packet with RakNet

I was wondering how to send packet to client in client-server architecture with RakNet. 我想知道如何使用RakNet在客户端-服务器体系结构中将数据包发送到客户端。 In this sample code we have this line: 在此示例代码中,我们具有以下这一行:

peer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);

However, the prototype is the following (from the interface class): 但是,原型如下(来自接口类):

virtual uint32_t Send( const RakNet::BitStream * bitStream,
                       PacketPriority priority,
                       PacketReliability reliability,
                       char orderingChannel,
                       const AddressOrGUID systemIdentifier,
                       bool broadcast,
                       uint32_t forceReceiptNumber=0 )=0;

As you can see, the 5th parameter takes a AddressOrGUID, it means we can send the SystemAddress as in the sample, but also can send the unique GUID of a connected machine. 如您所见,第5个参数采用AddressOrGUID,这意味着我们可以像示例中那样发送SystemAddress,但也可以发送所连接机器的唯一GUID。

There is a function called: 有一个函数叫做:

RakNet::GetSystemAddressFromGUID();

But I'm not sure if RakNet uses it to convert the GUID we can send as a parameter (I didn't find any use of this method in RakPeer (implemention of RakPeerInterface) and I'm not able to find how buffered packet are sent each tick). 但是我不确定RakNet是否使用它来转换我们可以作为参数发送的GUID(我在RakPeer(RakPeerInterface的实现)中未找到此方法的使用),也无法找到缓冲数据包的状态发送每个滴答声)。

The problem is the following: 问题如下:

The sample code replies directly to the received packet. 示例代码直接回复收到的数据包。 However, in a game, server has to send information without receiving packet from client. 但是,在游戏中,服务器必须发送信息而不接收来自客户端的数据包。 So I don't have access to something like 所以我无权访问

packet->systemAddress

because there is no received packet. 因为没有收到数据包。

So I will have to stock something in my Player class to know how to send them packets: SystemAddress or RakNetGUID. 因此,我将不得不在Player类中存储一些东西,以了解如何向其发送数据包:SystemAddress或RakNetGUID。 RakNetGUID is simpler and lighter to stock than a SystemAddress. 与SystemAddress相比,RakNetGUID的库存更简单,更轻便。

But, if RakNet uses GetSystemAddressFromGUID(), it's not worth because is has a O(log(n)) algorithm. 但是,如果RakNet使用GetSystemAddressFromGUID(),则不值得,因为它具有O(log(n))算法。

Do I need to stock the SystemAddress for each Player myself or RakNet::Send() doesn't use this method with a RakNetGUID ? 我是否需要为每个玩家自己存储SystemAddress,或者RakNet :: Send()不在RakNetGUID中使用此方法?

Thank you! 谢谢!

Ok I just did a mistake by not correctly following condition statement the first time I tried to understand the source code, and because this question is really specific, I think it would be great to look in source code. 好的,我第一次尝试理解源代码时没有正确遵循条件语句就犯了一个错误,并且由于这个问题确实很具体,所以我认为最好查看源代码。

The simple answer is Yes, store RakNetGUID in Player class 简单的答案是,将RakNetGUID存储在Player类中

Details here: 详细信息在这里:

Ok so first, file concerned is RakPeer.cpp only. 好的,首先,有关文件仅是RakPeer.cpp。 The starting point is: 起点是:

uint32_t RakPeer::Send( const RakNet::BitStream * bitStream,
                        PacketPriority priority,
                        PacketReliability reliability,
                        char orderingChannel,
                        const AddressOrGUID systemIdentifier,
                        bool broadcast,
                        uint32_t forceReceiptNumber ) // Line 1366

Then, we have this line where SendBuffered is called: 然后,在此行中调用SendBuffered:

SendBuffered((const char*)bitStream->GetData(),
             bitStream->GetNumberOfBitsUsed(),
             priority,
             reliability,
             orderingChannel,
             systemIdentifier, // This is the initial AddressOrGUID
             broadcast,
             RemoteSystemStruct::NO_ACTION,
             usedSendReceipt); // Line 1408

In the method above, we can know the name of the buffer variable: 在上面的方法中,我们可以知道缓冲区变量的名称:

bufferedCommands.Push(bcs); // Line 4216

And by searching every place where bufferedCommands is used, we find a meaningful method name: 通过搜索使用bufferedCommands的每个位置,我们找到了一个有意义的方法名称:

bool RakPeer::RunUpdateCycle(BitStream &updateBitStream ) // Line 5567

We can find a loop that sends every buffered message here: 我们可以在此处找到一个发送所有缓冲消息的循环:

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() will ask RakPeer::GetSystemIndexFromGuid() to find the appropriate Index: RakPeer :: SendImmediate()将要求RakPeer :: GetSystemIndexFromGuid()查找适当的索引:

else if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
        remoteSystemIndex=GetSystemIndexFromGuid(systemIdentifier.rakNetGuid); // Line 4300

Finally, this last method will store the index directly in the RakNet::RakNetGUID when found: 最后,找到后一个方法将直接将索引存储在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

If we call Send() with RakNetGUID, then it will check if RakNetGUID::systemIndex is set. 如果我们使用RakNetGUID调用Send(),则它将检查是否设置了RakNetGUID :: systemIndex。 If yes, it doesn't need to search. 如果是,则无需搜索。 Else, it will have a linear searching time O(n) (n = maximumNumbersOfPeers) for the first packet sent. 否则,它将对发送的第一个数据包具有线性搜索时间O(n)(n = maximumNumbersOfPeers)。

I wrote this to help people understand how it works if they have the same question in mind. 我写这篇文章的目的是帮助人们了解相同的问题时的工作原理。

From the doc : http://www.raknet.net/raknet/manual/systemaddresses.html 从文档中: http : //www.raknet.net/raknet/manual/systemaddresses.html

It is preferred that you refer to remote systems by RakNetGUID, instead of SystemAddress. 最好通过RakNetGUID而不是SystemAddress引用远程系统。 RakNetGUID is a unique identifier for an instance of RakPeer, while SystemAddress is not. RakNetGUID是RakPeer实例的唯一标识符,而SystemAddress则不是。 And it is necessary to exclusively use RakNetGUID if you plan to use the Router2 plugin. 如果计划使用Router2插件,则必须专门使用RakNetGUID。

SystemAddress is only the combination of the IP and the port SystemAddress只是IP和端口的组合

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM