標籤:
本文基於networkcomms2.3.1開源版本 gplv3協議
我們自己寫的處理方法都稱之為自訂處理方法
比如,我們在伺服器上寫的與登陸相關的處理方法:
NetworkComms.AppendGlobalIncomingPacketHandler<LoginContract>("ReqLogin", IncomingLoginRequest);
private void IncomingLoginRequest(PacketHeader header, Connection connection, LoginContract loginContract) { try { string resMsg=""; //為了簡單,這裡不調用資料庫,而是類比一下登入 if (loginContract.UserID == "1000" && loginContract.PassWord == "123") resMsg = "登入成功"; else resMsg = "使用者名稱密碼錯誤"; //把返回結果寫入到契約類中,後面返回給用戶端 ResMsgContract contract = new ResMsgContract(); contract.Message = resMsg; connection.SendObject("ResLogin", contract); } catch (Exception ex) { } }
通過以上的寫法,當伺服器器收到訊息類型為“ReqLogin"的訊息時,會自動擷取到相關的處理方法。
我們看一下背後的運行機制。
首先看註冊語句:
NetworkComms.AppendGlobalIncomingPacketHandler<LoginContract>("ReqLogin", IncomingLoginRequest);
AppendGlobalIncomingPacketHandler()方法,把訊息類型”ReqLogin"和處理方法“INcomingLoginRequest"添加到NetworkComms靜態類的字典中:
在AppendGlobalIncomingPacketHander<T>方法中 ,我們的處理方法 IncomingLoginRequest 與 PacketHandlerCallBackDelegate<T>參數相對應。
來看一下PacketHandlerCallBackDelegate的定義
public delegate void PacketHandlerCallBackDelegate<T>(PacketHeader packetHeader, Connection connection, T incomingObject);
AppendGlobalIncomingPacketHandler()方法如下:
public static void AppendGlobalIncomingPacketHandler<T>(string packetTypeStr, PacketHandlerCallBackDelegate<T> packetHandlerDelgatePointer) { if (packetTypeStr == null) throw new ArgumentNullException("packetTypeStr", "Provided packetType string cannot be null."); if (packetHandlerDelgatePointer == null) throw new ArgumentNullException("packetHandlerDelgatePointer", "Provided PacketHandlerCallBackDelegate<T> cannot be null."); if (sendReceiveOptions == null) throw new ArgumentNullException("sendReceiveOptions", "Provided SendReceiveOptions cannot be null."); lock (globalDictAndDelegateLocker) { if (globalIncomingPacketUnwrappers.ContainsKey(packetTypeStr)) { //Make sure if we already have an existing entry that it matches with the provided if (!globalIncomingPacketUnwrappers[packetTypeStr].Options.OptionsCompatible(sendReceiveOptions)) throw new PacketHandlerException("The proivded SendReceiveOptions are not compatible with existing SendReceiveOptions already specified for this packetTypeStr."); } else globalIncomingPacketUnwrappers.Add(packetTypeStr, new PacketTypeUnwrapper(packetTypeStr, sendReceiveOptions)); //Ad the handler to the list if (globalIncomingPacketHandlers.ContainsKey(packetTypeStr)) { //Make sure we avoid duplicates PacketTypeHandlerDelegateWrapper<T> toCompareDelegate = new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer); bool delegateAlreadyExists = false; foreach (var handler in globalIncomingPacketHandlers[packetTypeStr]) { if (handler == toCompareDelegate) { delegateAlreadyExists = true; break; } } if (delegateAlreadyExists) throw new PacketHandlerException("This specific packet handler delegate already exists for the provided packetTypeStr."); //把處理方法添加到相關字典中 globalIncomingPacketHandlers[packetTypeStr].Add(new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer)); } else globalIncomingPacketHandlers.Add(packetTypeStr, new List<IPacketTypeHandlerDelegateWrapper>() { new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer) }); if (LoggingEnabled) logger.Info("Added incoming packetHandler for ‘" + packetTypeStr + "‘ packetType."); } }
字典:
static Dictionary<string, List<IPacketTypeHandlerDelegateWrapper>> globalIncomingPacketHandlers = new Dictionary<string, List<IPacketTypeHandlerDelegateWrapper>>();
我們看到上面有一句:
PacketTypeHandlerDelegateWrapper<T> toCompareDelegate = new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer);
看一下PacketTypeHandlerDelegateWrapper類,此類把處理方法作為參數。
我們看一下此類:
class PacketTypeHandlerDelegateWrapper<T> : IPacketTypeHandlerDelegateWrapper { NetworkComms.PacketHandlerCallBackDelegate<T> innerDelegate; public PacketTypeHandlerDelegateWrapper(NetworkComms.PacketHandlerCallBackDelegate<T> packetHandlerDelegate) { this.innerDelegate = packetHandlerDelegate; } public object DeSerialize(MemoryStream incomingBytes, SendReceiveOptions options) { if (incomingBytes == null) return null; //if (incomingBytes == null || incomingBytes.Length == 0) return null; else //{ //if (options.DataSerializer == null) // throw new ArgumentNullException("options", "The provided options.DataSerializer was null. Cannot continue with deserialise."); return options.DataSerializer.DeserialiseDataObject<T>(incomingBytes, options.DataProcessors, options.Options); //} } public void Process(PacketHeader packetHeader, Connection connection, object obj) { innerDelegate(packetHeader, connection, (obj == null ? default(T) : (T)obj)); } public bool Equals(IPacketTypeHandlerDelegateWrapper other) { if (innerDelegate == (other as PacketTypeHandlerDelegateWrapper<T>).innerDelegate) return true; else return false; } public bool EqualsDelegate(Delegate other) { return other as NetworkComms.PacketHandlerCallBackDelegate<T> == innerDelegate; } }
感覺這一章寫的不太清楚,水平有限,您可以自行閱讀一下networkcomms2.3.1開源版本的原始碼,擷取會看的比較清晰:)
www.cnblogs.com/networkcomms
www.networkcomms.cn
c#網路通訊架構networkcomms核心解析之九 自訂處理方法的運行機制