為每個 RMI 函數指定單獨的 ID
global {} 中的 RMI 函數被指派了序列值 RMI ID。
若要取得所需的 RMI ID 值,請參閱下方的 [id=xxx] 語法。
global MedivalWorld 10000
{
Foo([in] int x); // id=10001 自動分配
[id=13000] id=Foo2([in] int y); // 強制指定為 id=13000
}
維持舊的發送和接收方式
將ProudNet引入使用過去的發送/接收處理方法建立的程式時,建議更改為RMI方法。 它可以防止程式設計師錯誤地建立發送/接收例程而犯錯,使以後的開發更加方便。
但是,如果您確實需要 RMI 以外的舊傳輸/接收處理方法,我們提供以下替代方法。
- 無需 RMI 即可發送和接收自訂訊息
以下函數用於在不使用Remote Method Invocation的情況下傳送使用者定義的訊息。
- 使用 RMI 參數發送和接收使用者定義的訊息
// 在ProudNet中,Proud.ByteArray類型
// 可以用作RMI參數,如下所示。
Foo([in] Proud::ByteArray something);
// --- PIDL 到這裡
// 這允許您使用過去的傳輸和接收處理例程。
// 傳送訊息時,將在過去的訊息傳送例程中建立的緩衝區物件插入 Proud.ByteArray 物件中。
// 然後,Proud.ByteArray 物件作為 RMI 的參數發送。
// 建立訊息對象
Proud::CMessage msg;
/* 使用者建立的 msg 物件尚未指定使用哪個緩衝區。
在這些情況下,您必須呼叫 UseInternalBuffer 才能使 << 運算子發揮作用。
UseInternalBuffer 假定 msg 物件中未指定緩衝區使用。
因此,如果已指定緩衝區使用情況,則不應呼叫此方法。
有關更多詳細信息,請參閱 Proud.CMessage.UseInternalBuffer 幫助。*/
msg.UseInternalBuffer();
msg << a << b;
Proud::ByteArray block;
block.SetCount(msg.GetLength());
memcpy(block.GetData(), msg.GetData(), block.Count);
Foo(Proud::HostID_Server, Proud::RmiContext::ReliableSend, block);
// 接收訊息時,Proud.ByteArray 物件作為開發人員實作的 RMI 函數內的 RMI 參數被接收,
// 提取您需要的資料。
DEFRMI_MyPIDL_Foo(MyClass)
{
// Parameter 'block' and the others are is given
Proud::CMessage msg;
msg.UseExternalBuffer(block.GetData(), block.Count);
msg.SetLength(block.Count);
msg >> a >> b;
...
}
// 要在 C# 中使用 ByteArray,必須在 PIDL 中設定它,如下所示。
rename cs(Proud::ByteArray, Nettention.Proud.ByteArray);
// 在ProudNet中,Proud.ByteArray類型
// 可以用作RMI參數,如下所示。
Foo([in] Proud::ByteArray something);
// --- PIDL 到這裡
// 訊息發送範例
string msg = "Welcome";
byte[] msgBytes = Encoding.UTF8.GetBytes(msg);
Nettention.Proud.ByteArray ar = new Nettention.Proud.ByteArray(msgBytes);
simpleProxy.Foo(Nettention.Proud.HostID.HostID_Server, Nettention.Proud.RmiContext.ReliableSend, ar);
// 接收訊息時,Proud.ByteArray 物件作為開發人員實作的 RMI 函數內的 RMI 參數被接收,
// 提取您需要的資料。
simpleStub.Foo = (remote, rmi, somthing) => {
string msg = Convert.ToBase64String(somthing.data);
};
存取所有 RMI 呼叫點
ProudNet 有一個可以存取 RMI 呼叫時間的設備。
透過測量每個 RMI 的執行時間來優化遊戲伺服器效能
- 從發送方(Proxy)存取呼叫點
1. 首先,為 PIDL 編譯器輸出建立一個 Proxy 衍生類別。
2. 覆蓋NotifySendByProxy
這將導致在每次發送時調用重寫的方法。
預設情況下,NotifySendByProxy()被設定為被調用,
為了進一步提高效能,如果您想要阻止 NotifySendByProxy() 呼叫本身,請將 m_enableNotifySendByProxy 設為 false,這樣 NotifySendByProxy() 將不再被呼叫。
- 存取接收方(Stub)呼叫點
1. 將Stub實例的成員變數m_enableStubProfiling(enableStubProfiling)設為true。
2. 重寫 PIDL 編譯器輸出的 Stub 衍生類別中的 BeforeRmiInvocation 和 AfterRmiInvocation。
這將導致每次接收時都呼叫重寫的方法。
BeforeRmiInvocation 在 RMI 執行即將到來之前調用,AfterRmiInvocation 在執行結束時調用。
這可以幫助您找到導致處理時間較長的伺服器效能問題的 RMI。
如何列印從存根接收的RMI函數的所有參數
將Stub實例的成員變數m_enableNotifyCallFromStub設為true並覆寫NotifyCallFromStub。
此方法接收轉換為字串的參數,因此您可以在此處留下日誌。
然而,由於RMI處理性能較低,建議僅在絕對必要時使用它。
在 C# 中,您可以使用定義的委託函數,而無需單獨重寫它。
同樣可以在定義的 Stub 物件中找到變數。
隱藏 RMI 名稱
為了在BeforeRmiInvocation等顯示主機傳送和接收的RMI的名稱,可以將所有RMI的名稱儲存在一個執行檔中。
但是,如果您出於安全原因想要隱藏它,請按照以下步驟操作。
在將 ..._proxy.cpp include在 PIDL 編譯結果中之前,將其定義如下。
#define HIDE_RMI_NAME_STRING
從版本 1.7.36365 開始,出於安全原因,RMI 函數名稱預設不會出現在 IRmiStub.BeforeRmiInvocation 函數中。
為了顯示PIDL編譯結果的代理,在編譯cpp原始檔之前,
它的定義如下。
#define USE_RMI_NAME_STRING
Last updated