簡體   English   中英

使用RakNet發送數據包的最佳方法

[英]Best way to send packet with RakNet

我想知道如何使用RakNet在客戶端-服務器體系結構中將數據包發送到客戶端。 在此示例代碼中,我們具有以下這一行:

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的實現)中未找到此方法的使用),也無法找到緩沖數據包的狀態發送每個滴答聲)。

問題如下:

示例代碼直接回復收到的數據包。 但是,在游戲中,服務器必須發送信息而不接收來自客戶端的數據包。 所以我無權訪問

packet->systemAddress

因為沒有收到數據包。

因此,我將不得不在Player類中存儲一些東西,以了解如何向其發送數據包:SystemAddress或RakNetGUID。 與SystemAddress相比,RakNetGUID的庫存更簡單,更輕便。

但是,如果RakNet使用GetSystemAddressFromGUID(),則不值得,因為它具有O(log(n))算法。

我是否需要為每個玩家自己存儲SystemAddress,或者RakNet :: Send()不在RakNetGUID中使用此方法?

謝謝!

好的,我第一次嘗試理解源代碼時沒有正確遵循條件語句就犯了一個錯誤,並且由於這個問題確實很具體,所以我認為最好查看源代碼。

簡單的答案是,將RakNetGUID存儲在Player類中

詳細信息在這里:

好的,首先,有關文件僅是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)。

我寫這篇文章的目的是幫助人們了解相同的問題時的工作原理。

從文檔中: http : //www.raknet.net/raknet/manual/systemaddresses.html

最好通過RakNetGUID而不是SystemAddress引用遠程系統。 RakNetGUID是RakPeer實例的唯一標識符,而SystemAddress則不是。 如果計划使用Router2插件,則必須專門使用RakNetGUID。

SystemAddress只是IP和端口的組合

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM