首页 > 代码库 > Connection类之ConnectionDelegatesHandlers.cs(NetworkComms 2.3.1源码了解和学习)

Connection类之ConnectionDelegatesHandlers.cs(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议。因为不能公开3.x版本的源码,所以基于此版本进行学习。3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大。 
namespace NetworkCommsDotNet{    /// <summary>    /// Connection对象  这个类是TcpConnection和 UDPConnnection连接类的父类    /// Connection由以下五个文件组成 大家注意到每个类前面都有个 partial关键字    /// ConnectionCreate.cs <1>    /// ConnectionDelegatesHandlers.cs <2>    /// ConnectionIncomingData.cs <3>    /// ConnectionSendClose.cs <4>    /// ConnectionStatic.cs  <5>    /// </summary>    public abstract partial class Connection    {        /// <summary>        ///线程安全锁        /// </summary>        protected object delegateLocker = new object();        /// <summary>        /// 默认的收发参数        /// </summary>        public SendReceiveOptions ConnectionDefaultSendReceiveOptions { get; protected set; }        /// <summary>        /// 一个与连接关闭相关的委托        /// </summary>        private NetworkComms.ConnectionEstablishShutdownDelegate ConnectionSpecificShutdownDelegate { get; set; }        /// <summary>        /// By default all incoming objects are handled using ConnectionDefaultSendReceiveOptions. Should the user want something else        /// those settings are stored here        /// </summary>        private Dictionary<string, PacketTypeUnwrapper> incomingPacketUnwrappers = new Dictionary<string, PacketTypeUnwrapper>();        /// <summary>        /// A connection specific incoming packet handler dictionary. These are called before any global handlers        /// </summary>        private Dictionary<string, List<IPacketTypeHandlerDelegateWrapper>> incomingPacketHandlers = new Dictionary<string, List<IPacketTypeHandlerDelegateWrapper>>();        /// <summary>        /// Returns the <see cref="SendReceiveOptions"/> to be used for the provided <see cref="PacketHeader"/>. Ensures there will not be a serializer / data processor clash for different delegate levels.        /// </summary>        /// <param name="header">The <see cref="PacketHeader"/> options are desired.</param>        /// <returns>The requested <see cref="SendReceiveOptions"/></returns>        private SendReceiveOptions IncomingPacketSendReceiveOptions(PacketHeader header)        {            //Are there connection specific or global packet handlers?            bool connectionSpecificHandlers = false;            lock (delegateLocker) connectionSpecificHandlers = incomingPacketHandlers.ContainsKey(header.PacketType);            bool globalHandlers = NetworkComms.GlobalIncomingPacketHandlerExists(header.PacketType);            //Get connection specific options for this packet type, if there arn‘t any use the connection default options            SendReceiveOptions connectionSpecificOptions = PacketTypeUnwrapperOptions(header.PacketType);            if (connectionSpecificOptions == null) connectionSpecificOptions = ConnectionDefaultSendReceiveOptions;            //Get global options for this packet type, if there arn‘t any use the global default options            SendReceiveOptions globalOptions = NetworkComms.GlobalPacketTypeUnwrapperOptions(header.PacketType);            if (globalOptions == null) globalOptions = NetworkComms.DefaultSendReceiveOptions;            if (connectionSpecificHandlers && globalHandlers)            {                if (!connectionSpecificOptions.OptionsCompatible(globalOptions))                    throw new PacketHandlerException("Attempted to determine correct sendReceiveOptions for packet of type ‘" + header.PacketType + "‘. Unable to continue as connection specific and global sendReceiveOptions are not equal.");                //We need to combine options in this case using the connection specific option in preference if both are present                var combinedOptions = new Dictionary<string, string>(globalOptions.Options);                                foreach (var pair in connectionSpecificOptions.Options)                    combinedOptions[pair.Key] = pair.Value;                //If the header specifies a serializer and data processors we will autodetect those                if (header.ContainsOption(PacketHeaderLongItems.SerializerProcessors))                {                    DataSerializer serializer;                    List<DataProcessor> dataProcessors;                    DPSManager.GetSerializerDataProcessorsFromIdentifier(header.GetOption(PacketHeaderLongItems.SerializerProcessors), out serializer, out dataProcessors);                    return new SendReceiveOptions(serializer, dataProcessors, combinedOptions);                }                //Otherwise we will use options that were specified                return new SendReceiveOptions(connectionSpecificOptions.DataSerializer, connectionSpecificOptions.DataProcessors, combinedOptions);            }            else if (connectionSpecificHandlers)            {                //If the header specifies a serializer and data processors we will autodetect those                if (header.ContainsOption(PacketHeaderLongItems.SerializerProcessors))                {                    DataSerializer serializer;                    List<DataProcessor> dataProcessors;                    DPSManager.GetSerializerDataProcessorsFromIdentifier(header.GetOption(PacketHeaderLongItems.SerializerProcessors), out serializer, out dataProcessors);                    return new SendReceiveOptions(serializer, dataProcessors, connectionSpecificOptions.Options);                }                return connectionSpecificOptions;            }            else            {                //If the header specifies a serializer and data processors we will autodetect those                if (header.ContainsOption(PacketHeaderLongItems.SerializerProcessors))                {                    DataSerializer serializer;                    List<DataProcessor> dataProcessors;                    DPSManager.GetSerializerDataProcessorsFromIdentifier(header.GetOption(PacketHeaderLongItems.SerializerProcessors), out serializer, out dataProcessors);                    return new SendReceiveOptions(serializer, dataProcessors, globalOptions.Options);                }                //If just globalHandlers is set (or indeed no handlers atall we just return the global options                return globalOptions;            }        }        /// <summary>        /// Trigger connection specific packet delegates with the provided parameters. Returns true if connection specific handlers were executed.        /// </summary>        /// <param name="packetHeader">The packetHeader for which all delegates should be triggered with</param>        /// <param name="incomingObjectBytes">The serialised and or compressed bytes to be used</param>        /// <param name="options">The incoming sendReceiveOptions to use overriding defaults</param>        /// <returns>Returns true if connection specific handlers were executed.</returns>        public bool TriggerSpecificPacketHandlers(PacketHeader packetHeader, MemoryStream incomingObjectBytes, SendReceiveOptions options)        {            try            {                if (packetHeader == null) throw new ArgumentNullException("packetHeader", "Provided PacketHeader cannot not be null.");                if (incomingObjectBytes == null) throw new ArgumentNullException("incomingObjectBytes", "Provided MemoryStream cannot not be null for packetType " + packetHeader.PacketType);                if (options == null) throw new ArgumentNullException("options", "Provided SendReceiveOptions cannot not be null for packetType " + packetHeader.PacketType);                //We take a copy of the handlers list incase it is modified outside of the lock                List<IPacketTypeHandlerDelegateWrapper> handlersCopy = null;                lock (delegateLocker)                    if (incomingPacketHandlers.ContainsKey(packetHeader.PacketType))                        handlersCopy = new List<IPacketTypeHandlerDelegateWrapper>(incomingPacketHandlers[packetHeader.PacketType]);                if (handlersCopy == null)                    //If we have received an unknown packet type we ignore them on this connection specific level and just finish here                    return false;                else                {                    //Idiot check                    if (handlersCopy.Count == 0) throw new PacketHandlerException("An entry exists in the packetHandlers list but it contains no elements. This should not be possible.");                    //Deserialise the object only once                    object returnObject = handlersCopy[0].DeSerialize(incomingObjectBytes, options);                    //Pass the data onto the handler and move on.                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... passing completed data packet to selected connection specific handlers.");                    //Pass the object to all necessary delgates                    //We need to use a copy because we may modify the original delegate list during processing                    foreach (IPacketTypeHandlerDelegateWrapper wrapper in handlersCopy)                    {                        try                        {                            wrapper.Process(packetHeader, this, returnObject);                        }                        catch (Exception ex)                        {                            if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Fatal("An unhandled exception was caught while processing a packet handler for a packet type ‘" + packetHeader.PacketType + "‘. Make sure to catch errors in packet handlers. See error log file for more information.");                            NetworkComms.LogError(ex, "PacketHandlerErrorSpecific_" + packetHeader.PacketType);                        }                    }                }            }            catch (Exception ex)            {                //If anything goes wrong here all we can really do is log the exception                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Fatal("An exception occured in TriggerPacketHandler() for a packet type ‘" + packetHeader.PacketType + "‘. See error log file for more information.");                NetworkComms.LogError(ex, "PacketHandlerErrorSpecific_" + packetHeader.PacketType);            }            return true;        }        /// <summary>        /// Returns the packet type sendReceiveOptions possibly used to unwrap incoming data. If no specific options are registered returns null        /// </summary>        /// <param name="packetTypeStr">The packet type for which the <see cref="SendReceiveOptions"/> are required.</param>        /// <returns>The requested <see cref="SendReceiveOptions"/> otherwise null</returns>        public SendReceiveOptions PacketTypeUnwrapperOptions(string packetTypeStr)        {            SendReceiveOptions options = null;            //If we find a global packet unwrapper for this packetType we used those options            lock (delegateLocker)            {                if (incomingPacketUnwrappers.ContainsKey(packetTypeStr))                    options = incomingPacketUnwrappers[packetTypeStr].Options;            }            return options;        }        /// <summary>        /// Append a connection specific packet handler        /// </summary>        /// <typeparam name="T">The type of incoming object</typeparam>        /// <param name="packetTypeStr">The packet type for which this handler will be executed</param>        /// <param name="packetHandlerDelgatePointer">The delegate to be executed when a packet of packetTypeStr is received</param>        /// <param name="options">The <see cref="SendReceiveOptions"/> to be used for the provided packet type</param>        public void AppendIncomingPacketHandler<T>(string packetTypeStr, NetworkComms.PacketHandlerCallBackDelegate<T> packetHandlerDelgatePointer, SendReceiveOptions options)        {            if (packetTypeStr == null) throw new ArgumentNullException("packetTypeStr", "Provided packetType string cannot be null.");            if (packetHandlerDelgatePointer == null) throw new ArgumentNullException("packetHandlerDelgatePointer", "Provided NetworkComms.PacketHandlerCallBackDelegate<T> cannot be null.");            if (options == null) throw new ArgumentNullException("options", "Provided SendReceiveOptions cannot be null.");            lock (delegateLocker)            {                if (incomingPacketUnwrappers.ContainsKey(packetTypeStr))                {                    //Make sure if we already have an existing entry that it matches with the provided                    if (!incomingPacketUnwrappers[packetTypeStr].Options.OptionsCompatible(options))                        throw new PacketHandlerException("The proivded SendReceiveOptions are not compatible with existing SendReceiveOptions already specified for this packetTypeStr.");                }                else                    incomingPacketUnwrappers.Add(packetTypeStr, new PacketTypeUnwrapper(packetTypeStr, options));                             //Ad the handler to the list                if (incomingPacketHandlers.ContainsKey(packetTypeStr))                {                    //Make sure we avoid duplicates                    PacketTypeHandlerDelegateWrapper<T> toCompareDelegate = new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer);                    bool delegateAlreadyExists = false;                    foreach (var handler in incomingPacketHandlers[packetTypeStr])                    {                        if (handler == toCompareDelegate)                        {                            delegateAlreadyExists = true;                            break;                        }                    }                                            if (delegateAlreadyExists)                        throw new PacketHandlerException("This specific packet handler delegate already exists for the provided packetTypeStr.");                    incomingPacketHandlers[packetTypeStr].Add(new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer));                }                else                    incomingPacketHandlers.Add(packetTypeStr, new List<IPacketTypeHandlerDelegateWrapper>() { new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer) });                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Info("Added connection specific incoming packetHandler for ‘" + packetTypeStr + "‘ packetType with " + ConnectionInfo);            }        }        /// <summary>        /// Returns true if a packet handler exists for the provided packet type, on this connection        /// </summary>        /// <param name="packetTypeStr">The packet type for which to check incoming packet handlers</param>        /// <returns>True if a packet handler exists</returns>        public bool IncomingPacketHandlerExists(string packetTypeStr)        {            lock (delegateLocker)                return incomingPacketHandlers.ContainsKey(packetTypeStr);        }        /// <summary>        /// Returns true if the provided packet handler has been added for the provided packet type, on this connection.        /// </summary>        /// <param name="packetTypeStr">The packet type within which to check packet handlers</param>        /// <param name="packetHandlerDelgatePointer">The packet handler to look for</param>        /// <returns>True if a global packet handler exists for the provided packetType</returns>        public bool IncomingPacketHandlerExists(string packetTypeStr, Delegate packetHandlerDelgatePointer)        {            lock (delegateLocker)            {                if (incomingPacketHandlers.ContainsKey(packetTypeStr))                {                    foreach (var handler in incomingPacketHandlers[packetTypeStr])                        if (handler.EqualsDelegate(packetHandlerDelgatePointer))                            return true;                }            }            return false;        }        /// <summary>        /// Remove the provided delegate for the specified packet type        /// </summary>        /// <param name="packetTypeStr">Packet type for which this delegate should be removed</param>        /// <param name="packetHandlerDelgatePointer">The delegate to remove</param>        public void RemoveIncomingPacketHandler(string packetTypeStr, Delegate packetHandlerDelgatePointer)        {            lock (delegateLocker)            {                if (incomingPacketHandlers.ContainsKey(packetTypeStr))                {                    //Remove any instances of this handler from the delegates                    //The bonus here is if the delegate has not been added we continue quite happily                    IPacketTypeHandlerDelegateWrapper toRemove = null;                    foreach (var handler in incomingPacketHandlers[packetTypeStr])                    {                        if (handler.EqualsDelegate(packetHandlerDelgatePointer))                        {                            toRemove = handler;                            break;                        }                    }                    if (toRemove != null)                        incomingPacketHandlers[packetTypeStr].Remove(toRemove);                    if (incomingPacketHandlers[packetTypeStr] == null || incomingPacketHandlers[packetTypeStr].Count == 0)                    {                        incomingPacketHandlers.Remove(packetTypeStr);                        //Remove any entries in the unwrappers dict as well as we are done with this packetTypeStr                        if (incomingPacketHandlers.ContainsKey(packetTypeStr))                            incomingPacketHandlers.Remove(packetTypeStr);                        if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Info("Removed a connection specific packetHandler for ‘" + packetTypeStr + "‘ packetType. No handlers remain with " + ConnectionInfo);                    }                    else                        if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Info("Removed a connection specific packetHandler for ‘" + packetTypeStr + "‘ packetType. Handlers remain with " + ConnectionInfo);                }            }        }        /// <summary>        /// Removes all delegates for the provided packet type        /// </summary>        /// <param name="packetTypeStr">Packet type for which all delegates should be removed</param>        public void RemoveIncomingPacketHandler(string packetTypeStr)        {            lock (delegateLocker)            {                //We don‘t need to check for potentially removing a critical reserved packet handler here because those cannot be removed.                if (incomingPacketHandlers.ContainsKey(packetTypeStr))                {                    incomingPacketHandlers.Remove(packetTypeStr);                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Info("Removed all connection specific incoming packetHandlers for ‘" + packetTypeStr + "‘ packetType with " + ConnectionInfo);                }            }        }        /// <summary>        /// Removes all delegates for all packet types        /// </summary>        public void RemoveIncomingPacketHandler()        {            lock (delegateLocker)            {                incomingPacketHandlers = new Dictionary<string, List<IPacketTypeHandlerDelegateWrapper>>();                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Info("Removed all connection specific incoming packetHandlers for all packetTypes with " + ConnectionInfo);            }        }        /// <summary>        /// Add a connection specific shutdown delegate        /// </summary>        /// <param name="handlerToAppend">The delegate to call when a connection is shutdown</param>        public void AppendShutdownHandler(NetworkComms.ConnectionEstablishShutdownDelegate handlerToAppend)        {            lock (delegateLocker)            {                if (ConnectionSpecificShutdownDelegate == null)                    ConnectionSpecificShutdownDelegate = handlerToAppend;                else                    ConnectionSpecificShutdownDelegate += handlerToAppend;                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Added a connection specific shutdown delegate to connection with " + ConnectionInfo);            }        }        /// <summary>        /// Remove a connection specific shutdown delegate.        /// </summary>        /// <param name="handlerToRemove">The delegate to remove for shutdown events</param>        public void RemoveShutdownHandler(NetworkComms.ConnectionEstablishShutdownDelegate handlerToRemove)        {            lock (delegateLocker)            {                ConnectionSpecificShutdownDelegate -= handlerToRemove;                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Removed ConnectionSpecificShutdownDelegate to connection with " + ConnectionInfo);                if (ConnectionSpecificShutdownDelegate == null)                {                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Info("No handlers remain for ConnectionSpecificShutdownDelegate with " + ConnectionInfo);                }                else                {                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Info("Handlers remain for ConnectionSpecificShutdownDelegate with " + ConnectionInfo);                }            }        }    }}

 

来自英国剑桥的c#网络通讯框架  开源版本: networkcomms2.3.1  可以进入此页面下载 networkcomms网络通讯框架学习 

【开源下载】基于TCP网络通信的即时聊天系统(IM系统)(c#源码)

[源码下载]Demo2.模拟简单登陆-效果图 基于networkcomms2.3.1

[源码下载]Demo1 客户端从服务器获取信息(基于networkcomms2.3.1)

【开源下载】基于TCP网络通信的自动升级程序c#源码

【模板下载】分享我所使用的数据库框架

【模板下载】innosetup 制作.net安装包的模板

 

【模板下载】分享我所使用的数据库框架

Connection类之ConnectionDelegatesHandlers.cs(NetworkComms 2.3.1源码了解和学习)