詞彙表
📚 Burst Time
Burst time主要分爲CPU burst time和Device burst time。
- CPU burst time
運行特定例程只運算 CPU 的時間 。 CPU burst time 線程的 CPU 核心佔用率爲 100 。
- Device burst time
這是CPU在執行特定例程時等待其他處理完成的時間。Device burst time中執行緒的CPU核心使用率為0。 CPU 等待其他處理完成的典型情況包括讀取/寫入檔案、執行資料庫查詢或等待其他主機的服務回應。
📚 C++ Singleton
Singleton和全局變量在C++語言中存在差異。 全局變量在運行 WinMain() 或 main() 時不會在即將退出時被破壞, 而會在子調用函數中被破壞 。 全局變量的破壞順序只能在一個C++文件的編譯結果中保證,不同C++文件的編譯結果之間的破壞順序不能保證。
但是 C++ singleton 在 WinMain() 或 main() 返回之前被調用 。 此外,實例的創建者會在第一次訪問 singleton 的瞬間被調用,破壞的順序也會被調用者反向調用。 因此,它確保了比全局變量更安全的生成/破壞規則。
上述實現存在如下風險:如果在短時間內同時從多個線程訪問singleton,則生成器可能會有2次以上的呼叫。
在解決這些問題的同時,我們建議使用無critical section負載的類Proud.CSingleton訪問。
📚 DB Constraints
要進入字段的值如果不滿足特定條件,就指不讓進入。
PrimaryKey Unique Index 其他等等(>,<,=,!=),Constraints由Unique Index, Trigger 等實現。
📚 Fast Heap
ProudNet的Fastheap雖然比Lookaside allocator稍微慢一些,但比OS環境下的存儲器分配/解除速度更快,可以分配/解除各種大小的存儲器塊。
ProudNet 的 Fast heap 的實現類是 Proud.CFastHeap。 Proud.CFastHeap 和 Lookaside allocator 一樣, 只有在所有存儲塊被破壞之後才能移除 Proud.CFastHeap 對象。
Fast heap的使用方法如下。
首先以Proud.CFastHeap.New方法生成fastheap對象。 創建全局對象也可以。
用 Proud.CFastHeap.Alloc 方法分配內存塊 。
解除爲Proud.CFastHeap.Free。 可以用CFastHeap.Realloc重新分配內存塊。
解除所有存儲塊後,破壞 Proud.CFastHeap 對象。
📚 P2P 組
如果兩個客戶端A和B要進行P2P通信,則A和B必須屬於至少一個P2P組。 多人可以在一個聊天視窗中互相聊天,也可以透過建立多個聊天視窗來進行多人聊天。 但是,您無法在您不在的聊天視窗中聊天。
ProudNet在網絡聊天工具中,每個聊天窗口對應P2P組。
但是,創建聊天窗口或進入其他聊天窗口的權限只有服務器纔有。 P2P 組標識符也是 Proud.HostID 類型。
📚 PIDL
PIDL是爲RMI自制的編譯器。
在特定文件中定義協議後設置,會自動創建對象文件。 此時生成的客體與Server和Client一起使用,因此生成Common(公用)Project進行管理非常方便。
📚 Reliable 訊息
Reliable消息(或reliable send)是指發送方發送的消息內容和順序始終由接收方統一接收。 例如,發送信息A、B、C、D、E後,接收方也會按照A、B、C、D、E的順序無損失地接收數據。
雖然具有可信度(reliablility)的優點,但偶爾接收的時間可能比Unreliable 信息慢。
📚 RMI
RMI(Remote Method Invocation, 遠程方法呼叫)是指呼叫其他網絡或其他程序中的函數,通過機器代替人進行定義收發例程和信息(Message)結構的編碼工作,起到將讓開發者感到吃力的編程工作(信息結構定義、發送函數、接收函數製作)簡化爲函數呼叫形式的作用。
發送消息時,調用 RMI 函數的一方稱爲 Proxy,調用方稱爲 Stub。
- 不使用 RMI 時
但是使用RMI可以整理成以下短代碼。
以上格式爲IDL(Interface Description Language)格式,編譯後生成C++或C#源。 創建的源文件由消息結構聲明、發送函數、接收處理函數等組成,即使開發者不直接創建網絡處理程序,PIDL編譯器也會自動生成。
在創建的文件中,將函數調用轉換爲消息發送到網絡的模塊稱爲proxy,分析通過網絡接收到的消息並調用用戶函數的模塊稱爲stub。
當從主機A調用RMI函數X時,實際上調用X的proxy,proxy將其切換爲網絡消息並將其發送到主機B。 然後主機B接收消息併發送到stub,stub分析後調用用戶創建的函數X。
因爲看起來具有與主機A呼叫主機B上的函數相似的形狀,所以具有Remote Method Invocation(遠程方法呼叫)的意義。
📚 Stored Procedure
Stored Procedure是由DBMS本身可放入的SQL語句製作的程序函數。 訪問數據庫時,查詢語句字符串由應用程序直接創建並扔出,但如果可能,提前創建Stored Procedure保存查詢語句例程,應用程序直接調用Stored Procedure在性能和穩定性(數據庫鎖定策略等)上更有效。
📚 Unreliable 訊息
Unreliable 信息(或unreliable send)可以根據通信線的長度和狀態,接收發送方發送的消息內容和順序不同。
例如,發送消息A、B、C、D、E時,接收方有時會收到A、B、C、D、E,但可能會收到兩次相同的信息(A,B,B,C,C,D和E),或者消息在中間丟失(A,B,D),或者消息會按順序不同到達。(A,C,B,E,D)
但是消息內部的數據不會被破壞。 雖然Unreliable消息具有這些缺點,但送達時間比Reliable 信息快。
📚 UUID 或 GUID
Unique or global universal identifier (UUID或GUID)是16字節大小的數據塊,生成的GUID在概率上是全世界唯一的。
ProudNet DB將UUID分配給每個Gamer、Hero、WorldObject。 雖然因爲UUID是16bytes,所以可以認爲大小比較大,但是UUID具有在地球上不重複的優點,所以在幾個重要案例中很有用。 最具代表性的是服務器整合、玩家賬號移動、玩家ID變更等。
參考 全域唯一識別碼
📚 競爭狀態 (Race Condition)
在工學領域,競爭狀態(race condition)是指同時進行兩個以上輸入或操作的狀態。 在這種情況下,有無法得出正常結果的危險,這被稱爲競爭危險。
在計算機科學中,競爭狀態是指多個過程試圖同時獲取共享資源的狀態,當同時獲取時,可能會出現破壞數據一致性的結果。 爲了防止這種情況的發生,需要過程協作技術。
📚 數據量化
當通過網絡交換浮動小數點單位的大值時,可能會出現減少數據包量的詭計。 例如,如果角色位置x值僅在100到200之間確定,小數點後兩位數的精度可以忽略不計, 此值可轉換爲 100 * 100 = 10000 或更少的值, 並節省 double (8 字節) 爲 word (2 字節) 。
這個技巧稱為量化(quantization)。
該類提供了量化和量化的相反給付功能。
📚 Listening Port
由主機地址和端口組成,服務器必須有一個listening port才能接收客戶端的訪問。
主機地址是互聯網上的地址,由111.222.111.222或mycomputer.mydomain.com 格式組成。 Port的值介於1,000到65500之間。 只要兩個或兩個以上的程序不使用相同的listening port,就可以任意指定。
📚 Marshaling
將RMI呼叫轉換爲信息或從信息中提取用於呼叫RMI的值稱爲marshaling。 ProudNet提供int或float等基本類型的Marshaling功能。
📚 Multicast
將一條信息一次性傳遞給多個主播的multicast, 將消息只傳遞給一個主機叫做unicast。
📚 Thread Pool
生成1條線程後,清除的過程會產生大量的通量,因此,如果運行中的線程較多,操作系統可能會超負荷運行。
因此,要保持儘可能少的線程,儘量減少線程的去除和生成過程,爲此,需要設置由一定數量組成的1個線程集合,只在必要時導入使用,必要時返回集合。 這個過程叫做thread pool。
即,thread pool是指由多個線程預先準備好的多個線程組成的一個集合。
- 例子
客戶端A、B、C被服務器容納的狀態下,分別因RMI或事件在Proud.CNetServer內的queue中等待的狀態。
A1,A2,A3 -> 客戶端 A 的事件或 RMI B1,B2,B3 -> 客戶端B的事件或RMI線程池共有兩個線程。 這時根據規則執行如下。
A1、A2、A3不能同時運行。
B1、B2、B3和C1、C2、C3同樣不是同時運行的。
A1、A2、A3之一和B1、B2、B3之一、C1、C2、C3之一可以同時運行。
由於線程池中只有2個線程,A、B、C中的2個線程被篩選並回饋,但回饋程序首先完成線程的線程對未篩選的客戶端進行RMI或事件回饋。
📚 推測導航(dead reckoning)
ProudNet爲了表現遊戲角色的流暢位置,提供推測導航(dead reckoning)工具。
推測導航大致以以下方式操作。
將移動角色的位置和速度從主機A傳送到主機B。 此時傳輸週期爲每秒2~10次。
傳輸週期最好是動態的。 只有當角色的加速度較大時,縮短傳輸週期才能同步更精確的運動。 加速度大的情況是,角色的速度急劇變化時或角色撞到其他物體,移動方向急劇變化時等。 (見下表)
在主機B中,通過pinging從主機A獲得消息到達所需的時間(延遲)。
當主機B接收到角色的位置、速度信息時,用以下公式預測主機A角色的實際位置。 P: 預測位置, V: 接收速度, T: 延遲, P0: 接收位置 P = (V * T) + P0
到這裏可以預測角色的位置,但租用計算出的位置值會導致角色的位置斷斷續續的問題。 使用 Proud.CPositionFollower 來解決這個問題。
Proud.CPositionFollower的作用是移動追蹤者(follower)使其在規定時間內到達移動目標位置。 特別是製作成可以直線追蹤移動的目標位置,可以減少其他主機角色位置的突出現象。
下面將描述實現推測導航的其餘步驟。
在主機 B 中,將預測的位置和速度值輸入到 Proud.CPositionFollower 對象中。 此時輸入目標位置、速度。
在主機B中,獲取Proud.CPositionFollower客體的示蹤劑位置,對主機A的角色位置進行渲染。
- 導航示例
P(t=0,1,2)是預測點,紅線是Proud.CPositionFollower校正的角色位置。 通常,最好將主機A中角色的位置發送週期和跟蹤者在Proud.CPositionFollower中到達目標位置的時間限制設定爲相同,角色位置發送週期因情況而異。
建議示例
情況 | 發送的數據類型 | 平均發送週期 | 快速增加的加速度示例 |
---|---|---|---|
大型戰RPG遊戲(MMORPG)玩家角色 | 位置(xyz),速度(xyz),觀望方向(z) | 0.3 | 角色的移動方向轉換,站立,圓點,波普 |
飛機或車輛 | 位置(xyz),速度(xyz),加速度(xyz), 觀望方向(xyz) | 0.3 | 障礙物碰撞、急轉彎 |
第一人稱射擊遊戲(FPS)玩家角色 | 位置(xyz), 觀望方向(xyz) | 0.03 | 角色移動方向改變後,狙擊槍發射瞬間 |
發送週期短時,可能會有發送量過大的危險,建議使用發送量自動調節功能 (Throttling)。
- 曲線型跟蹤器(Spline based follower)
Proud.CPositionFollower不僅提供直線,還提供曲線追擊目標的follower。 它是一種三階函數形式的曲線型跟蹤器(spline based follower)。 這顯示了它們以比直線型follower更光滑的形式追趕。 但是,並不總是呈現光滑的面貌,所以最好在遊戲玩法上邊測試邊選擇。
爲了獲得曲線型跟蹤器,請使用以下方法。
Proud.CPositionFollower.GetSplineFollowerPosition
Proud.CPositionFollower.GetSplineFollowerVelocity
角度的校正處理使用以下方法。
Proud.CPositionFollower: 位置補正作用
Proud.CAngleFollower: 角度的校準作用
📚 打孔 (Hole Punching)
路由器還具有路由器的特性,以製作Routing Table的P2P通信爲目的,事先與對方交換數據包,在各自的路由器上製作Routing Table。 確切的名稱是 STUN (Simple Traversal of User Datagram Protocol Through Network Address Translators)。
打孔方法如下:
Full Cone NAT
Restricted Cone
Port Restricted Cone
Symmetric Cone
Last updated