介绍开源的.net通信框架NetworkComms框架 源码分析(二十 )ConnectionCreate

原文网址: http://www.cnblogs.com/csdev

Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是:Apache License v2

开源地址是:https://github.com/MarcFletcher/NetworkComms.Net

 public abstract partial class Connection
    {
        /// <summary>
        /// Connection information related to this connection.
        /// 连接信息类
        /// </summary>
        public ConnectionInfo ConnectionInfo { get; protected set; }

        /// <summary>
        /// A manual reset event which can be used to handle connection setup and establish.
        /// 手动类型信号灯   连接创建 Setup
        /// </summary>
        protected ManualResetEvent connectionSetupWait = new ManualResetEvent(false);
        /// <summary>
        /// A manual reset event which can be used to handle connection setup and establish.
        /// 手动类型信号灯   连接创建  Establish
        /// </summary>
        protected ManualResetEvent connectionEstablishWait = new ManualResetEvent(false);

        /// <summary>
        /// A boolean used to signal a connection setup exception.
        /// 连接创建异常
        /// </summary>
        protected bool connectionSetupException = false;
        /// <summary>
        /// If <see cref="connectionSetupException"/> is true provides additional exception information.
        ///  连接创建异常 字符信息
        /// </summary>
        protected string connectionSetupExceptionStr = "";

        /// <summary>
        /// Create a new connection object
        /// 创建一个新的连接对象
        /// </summary>
        /// <param name="connectionInfo">连接信息  ConnectionInfo corresponding to the new connection</param>
        /// <param name="defaultSendReceiveOptions">收发参数 The SendReceiveOptions which should be used as connection defaults</param>
        protected Connection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions)
        {
            //If the application layer protocol is disabled the serialiser must be NullSerializer
            //and no data processors are allowed.
            //如果应用层协议禁用  序列化必须使用NullSerializer 并且不能使用处理器
            if (connectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Disabled)
            {
                if (defaultSendReceiveOptions.Options.ContainsKey("ReceiveConfirmationRequired"))
                    throw new ArgumentException("Attempted to create an unmanaged connection when the provided send receive" +
                        " options specified the ReceiveConfirmationRequired option. Please provide compatible send receive options in order to successfully" +
                        " instantiate this unmanaged connection.", "defaultSendReceiveOptions");

                if (defaultSendReceiveOptions.DataSerializer != DPSManager.GetDataSerializer<NullSerializer>())
                    throw new ArgumentException("Attempted to create an unmanaged connection when the provided send receive" +
                        " options serialiser was not NullSerializer. Please provide compatible send receive options in order to successfully" +
                        " instantiate this unmanaged connection.", "defaultSendReceiveOptions");

                if (defaultSendReceiveOptions.DataProcessors.Count > 0)
                    throw new ArgumentException("Attempted to create an unmanaged connection when the provided send receive" +
                        " options contains data processors. Data processors may not be used with unmanaged connections." +
                        " Please provide compatible send receive options in order to successfully instantiate this unmanaged connection.", "defaultSendReceiveOptions");
            }

            SendTimesMSPerKBCache = new CommsMath();
            packetBuilder = new PacketBuilder();

            //Initialise the sequence counter using the global value
            //Subsequent values on this connection are guaranteed to be sequential
            //初始化数据包顺序号  用的是networkcomms静态类中的值
            //顺序号不会重复
            packetSequenceCounter = Interlocked.Increment(ref NetworkComms.totalPacketSendCount);

            ConnectionInfo = connectionInfo;

            if (defaultSendReceiveOptions != null)
                ConnectionDefaultSendReceiveOptions = defaultSendReceiveOptions;
            else
                ConnectionDefaultSendReceiveOptions = NetworkComms.DefaultSendReceiveOptions;

            //Add any listener specific packet handlers if required
            //如果需要添加监听器指定的数据包处理器
            if (connectionInfo.ConnectionListener != null)
                connectionInfo.ConnectionListener.AddListenerPacketHandlersToConnection(this);

            if (NetworkComms.commsShutdown) throw new ConnectionSetupException("Attempting to create new connection after global NetworkComms.Net shutdown has been initiated.");

            if (ConnectionInfo.ConnectionType == ConnectionType.Undefined || ConnectionInfo.RemoteEndPoint == null)
                throw new ConnectionSetupException("ConnectionType and RemoteEndPoint must be defined within provided ConnectionInfo.");

            //If a connection already exists with this info then we can throw an exception here to prevent duplicates
            //如果一个相同的连接已经存在 我们抛出异常  防止重复
            if (NetworkComms.ConnectionExists(connectionInfo.RemoteEndPoint, connectionInfo.LocalEndPoint, connectionInfo.ConnectionType, connectionInfo.ApplicationLayerProtocol))
                throw new ConnectionSetupException("A " + connectionInfo.ConnectionType.ToString() + " connection already exists with info " + connectionInfo);

            //We add a reference in the constructor to ensure any duplicate connection problems are picked up here
            //添加连接引用到NetworkComms静态类中
            NetworkComms.AddConnectionReferenceByRemoteEndPoint(this);
        }

        /// <summary>
        /// Establish this connection
        /// 创建连接
        /// </summary>
        public void EstablishConnection()
        {
            try
            {
                bool connectionAlreadyEstablishing = false;
                lock (_syncRoot)
                {
                    if (ConnectionInfo.ConnectionState == ConnectionState.Established) return;
                    else if (ConnectionInfo.ConnectionState == ConnectionState.Shutdown) throw new ConnectionSetupException("Attempting to re-establish a closed connection. Please create a new connection instead.");
                    else if (ConnectionInfo.ConnectionState == ConnectionState.Establishing)
                        connectionAlreadyEstablishing = true;
                    else
                        ConnectionInfo.NoteStartConnectionEstablish();
                }

                if (connectionAlreadyEstablishing)
                {
                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace("Waiting for connection with " + ConnectionInfo + " to be established.");
                    if (!WaitForConnectionEstablish(NetworkComms.ConnectionEstablishTimeoutMS))
                        throw new ConnectionSetupException("Timeout waiting for connection to be successfully established.");
                }
                else
                {
                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace("Establishing new connection with " + ConnectionInfo);

                    EstablishConnectionSpecific();

                    if (ConnectionInfo.ConnectionState == ConnectionState.Shutdown) throw new ConnectionSetupException("Connection was closed immediately after handshake. This can occur if a different thread used and subsequently closed this connection.");

                    //Once the above has been done the last step is to allow other threads to use the connection
                    //在连接信息类中,标注连接创建完成
                    ConnectionInfo.NoteCompleteConnectionEstablish();

                    //Not all connection types will have a known remote network identifier
                    //所有的连接都有一个网络ID
                    if (ConnectionInfo.NetworkIdentifier != ShortGuid.Empty)
                        NetworkComms.AddConnectionReferenceByIdentifier(this);

                    connectionEstablishWait.Set();

                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... connection successfully established with " + ConnectionInfo);
                }
            }
            catch (SocketException e)
            {
                //If anything goes wrong we close the connection.
                //出现错误 关闭连接
                CloseConnection(true, 43);
                throw new ConnectionSetupException(e.ToString());
            }
            catch (Exception ex)
            {
                //If anything goes wrong we close the connection.
                //出现错误 关闭连接
                CloseConnection(true, 44);

                //For some odd reason not all SocketExceptions get caught above, so another check here
                //一些偶然的场合中,异常会到达此处
                if (ex.GetBaseException().GetType() == typeof(SocketException))
                    throw new ConnectionSetupException(ex.ToString());
                else
                    throw;
            }
        }

        /// <summary>
        /// Any connection type specific establish tasks. Should call at least ConnectionHandshake() or TriggerConnectionEstablishDelegates();
        /// 创建连接的抽象类
        /// </summary>
        protected abstract void EstablishConnectionSpecific();

        /// <summary>
        /// Performs a connection handshake with the remote end of the connection.
        /// Exchanges network identifier and any listener whose IPAddress matches the connection localEndPoint IPAddress.
        /// 连接握手  执行一个连接握手同远程的连接
        /// 交换网络ID等
        ///
        /// </summary>
        protected void ConnectionHandshake()
        {
            if (ConnectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Disabled)
                throw new CommunicationException("Attempted to perform handshake on connection where the application protocol has been disabled.");

            //If we are server side and we have just received an incoming connection we need to return a connection identifier
            //This id will be used in all future connections from this machine
            //如果我们是服务器端 我们接收到进入的连接并返回一个连接ID给他
            //这个ID将用于未来所有的本机连接
            if (ConnectionInfo.ServerSide)
            {
                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Waiting for client connnectionInfo from " + ConnectionInfo);

                //Wait for the client to send its identification
                //等待客户端发送它的ID
#if NET2
                if (!connectionSetupWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS, false))
#else
                if (!connectionSetupWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS))
#endif
                    throw new ConnectionSetupException("Timeout waiting for client connectionInfo with " + ConnectionInfo + ". Connection created at " + ConnectionInfo.ConnectionCreationTime.ToString("HH:mm:ss.fff") + ", its now " + DateTime.Now.ToString("HH:mm:ss.f"));

                if (connectionSetupException)
                {
                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Connection setup exception. ServerSide with " + ConnectionInfo + ", " + connectionSetupExceptionStr);
                    throw new ConnectionSetupException("ServerSide. " + connectionSetupExceptionStr);
                }

                //Trigger the connection establish delegates before replying to the connection establish
                //在回复连接创建之前触发连接创建委托
                TriggerConnectionEstablishDelegates();
            }
            else
            {
                //If we are client side part of the handshake is to inform the server of a potential local listener
                //Get a list of existing listeners
                //如果我们是握手中的客户端 通知服务器他有了一个潜在的本地听众
                List<EndPoint> existingLocalListeners = null;
                if (ConnectionInfo.LocalEndPoint is IPEndPoint)
                    existingLocalListeners = Connection.ExistingLocalListenEndPoints(ConnectionInfo.ConnectionType, new IPEndPoint(ConnectionInfo.LocalIPEndPoint.Address, 0));
#if NET4 || NET35
                else if (ConnectionInfo.LocalEndPoint is InTheHand.Net.BluetoothEndPoint)
                    existingLocalListeners = Connection.ExistingLocalListenEndPoints(ConnectionInfo.ConnectionType, new InTheHand.Net.BluetoothEndPoint(ConnectionInfo.LocalBTEndPoint.Address, ConnectionInfo.LocalBTEndPoint.Service));
#endif

                //Check to see if we have a local listener for matching the local endpoint address
                //If we are client side we use this local listener in our reply to the server
                //检查我们是否有一个本地的监听器来对应本地的端点地址
                //如果我们作为客户端,我们可以使用本地监听器来回复服务器端
                EndPoint selectedExistingLocalListenerEndPoint = null;
                if (existingLocalListeners != null && // If we have a suitable local listener  如果我们有合适的本地监听器
                    existingLocalListeners.Count > 0 && // If we have a suitable local listener 如果我们有合适的本地监听器
                    !existingLocalListeners.Contains(ConnectionInfo.RemoteEndPoint)) //If this is not an application loop back connection  如果这不是一个应用的回调连接
                    selectedExistingLocalListenerEndPoint = (existingLocalListeners.Contains(ConnectionInfo.LocalEndPoint) ? ConnectionInfo.LocalEndPoint : existingLocalListeners[0]);

                //During this exchange we may note an update local listen port
                //我们可以注意到一个更新的本地监听端口
                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Sending connnectionInfo to " + ConnectionInfo);

                //Pull-out the parameters we want to send to the server  找出我们想要发送到服务器的参数
                //Doing it here rather than all in the following Send Object line keeps it clearer
                EndPoint selectedLocalListenerEndPoint = (selectedExistingLocalListenerEndPoint != null ? selectedExistingLocalListenerEndPoint : ConnectionInfo.LocalEndPoint);
                bool connectable = selectedExistingLocalListenerEndPoint != null;

                //As the client we initiated the connection we now forward our local node identifier to the server
                //If we are listening we include our local listen port as well
                //作为客户端我们发送本地ID给服务器
                //如果我们监听 我们包含本地监听端口
                SendObject(Enum.GetName(typeof(ReservedPacketType), ReservedPacketType.ConnectionSetup), new ConnectionInfo(ConnectionInfo.ConnectionType,
                    NetworkComms.NetworkIdentifier,
                    selectedLocalListenerEndPoint,
                    connectable),
                    NetworkComms.InternalFixedSendReceiveOptions);

                //Wait here for the server end to return its own identifier
                //在这里等待服务器端返回其自己的标识符
#if NET2
                if (!connectionSetupWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS, false))
#else
                if (!connectionSetupWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS))
#endif
                    throw new ConnectionSetupException("Timeout waiting for server connnectionInfo from " + ConnectionInfo + ". Connection created at " + ConnectionInfo.ConnectionCreationTime.ToString("HH:mm:ss.fff") + ", its now " + DateTime.Now.ToString("HH:mm:ss.f"));

                //If we are client side we can update the localEndPoint for this connection to reflect what the remote end might see if we are also listening
                //如果我们是客户端 我们更新本地端点
                if (selectedExistingLocalListenerEndPoint != null && selectedExistingLocalListenerEndPoint != ConnectionInfo.LocalEndPoint)
                {
                    //We should now be able to set the connectionInfo localEndPoint
                    //设置连接信息类的本地端点
                    NetworkComms.UpdateConnectionReferenceByEndPoint(this, ConnectionInfo.RemoteEndPoint, selectedExistingLocalListenerEndPoint);
                    ConnectionInfo.UpdateLocalEndPointInfo(selectedExistingLocalListenerEndPoint);
                }

                if (connectionSetupException)
                {
                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Connection setup exception. ClientSide with " + ConnectionInfo + ", " + connectionSetupExceptionStr);
                    throw new ConnectionSetupException("ClientSide. " + connectionSetupExceptionStr);
                }

                //Trigger the connection establish delegates once the server has replied to the connection establish
                //如果服务器已经针对连接创建有回复  触发连接创建委托
                TriggerConnectionEstablishDelegates();
            }
        }

        /// <summary>
        /// Trigger connection establish delegates.
        /// 触发连接创建委托
        /// </summary>
        protected void TriggerConnectionEstablishDelegates()
        {
            //Call asynchronous connection establish delegates here
            //同步调用连接创建委托
            if (NetworkComms.globalConnectionEstablishDelegatesAsync != null)
            {
                NetworkComms.CommsThreadPool.EnqueueItem(QueueItemPriority.Normal, new WaitCallback((obj) =>
                {
                    Connection connectionParam = obj as Connection;
                    NetworkComms.globalConnectionEstablishDelegatesAsync(connectionParam);
                }), this);
            }

            //Call synchronous connection establish delegates here
            //同步调用连接创建委托
            if (NetworkComms.globalConnectionEstablishDelegatesSync != null)
                NetworkComms.globalConnectionEstablishDelegatesSync(this);
        }

        /// <summary>
        /// Return true if the connection is established within the provided timeout, otherwise false
        /// 如果连接在指定的时间内建设完成 返回True
        /// </summary>
        /// <param name="waitTimeoutMS">超时时间   Wait time in milliseconds before returning</param>
        /// <returns>True if the wait was triggered, false otherwise after the provided timeout.</returns>
        protected bool WaitForConnectionEstablish(int waitTimeoutMS)
        {
            if (ConnectionInfo.ConnectionState == ConnectionState.Established)
                return true;
            else
            {
                if (NetworkComms.LoggingEnabled)
                    NetworkComms.Logger.Trace("Waiting for new connection to be successfully established before continuing with " + ConnectionInfo);

                if (ConnectionInfo.ConnectionState == ConnectionState.Shutdown)
                    throw new ConnectionShutdownException("Attempted to wait for connection establish on a connection that is already shutdown.");

#if NET2
                return connectionSetupWait.WaitOne(waitTimeoutMS, false);
#else
                return connectionSetupWait.WaitOne(waitTimeoutMS);
#endif
            }
        }

        /// <summary>
        /// Handle an incoming ConnectionSetup packet type
        /// 处理一个连接创建类型的数据包
        /// </summary>
        /// <param name="packetDataSection">Serialised handshake data</param>
        internal void ConnectionSetupHandler(MemoryStream packetDataSection)
        {
            //We should never be trying to handshake an established connection
            //我们不要尝试与已经创建的连接握手
            ConnectionInfo remoteConnectionInfo = NetworkComms.InternalFixedSendReceiveOptions.DataSerializer.DeserialiseDataObject<ConnectionInfo>(packetDataSection,
                NetworkComms.InternalFixedSendReceiveOptions.DataProcessors, NetworkComms.InternalFixedSendReceiveOptions.Options);

            if (ConnectionInfo.ConnectionType != remoteConnectionInfo.ConnectionType)
            {
                connectionSetupException = true;
                connectionSetupExceptionStr = "Remote connectionInfo provided connectionType did not match expected connection type.";
            }
            else
            {
                //We use the following bool to track a possible existing connection which needs closing
                //我们使用下面的布尔值跟踪一个可能存在的需要关闭的连接
                bool possibleClashWithExistingConnection = false;
                Connection existingConnection = null;

                //We first try to establish everything within this lock in one go
                //我们首先尝试在锁的内部解决这个问题
                //If we can‘t quite complete the establish we have to come out of the lock at try to sort the problem
                //如果我们不能很好的完成创建工作  我们可能需要到锁外面重新解决这个问题
                bool connectionEstablishedSuccess = ConnectionSetupHandlerFinal(remoteConnectionInfo, ref possibleClashWithExistingConnection, ref existingConnection);

                //If we were not successful at establishing the connection we need to sort it out!
                //如果连接没有成功建立 我们需要解决这个问题
                if (!connectionEstablishedSuccess && !connectionSetupException)
                {
                    if (existingConnection == null) throw new Exception("Connection establish issues and existingConnection was left as null.");

                    if (possibleClashWithExistingConnection)
                    {
                        //If we have a clash by endPoint we test the existing connection
                        //如果我们在此端点遇到冲突 我们将测试已经存在的连接
                        if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Existing connection with " + ConnectionInfo + ". Testing existing connection.");
                        if (existingConnection.ConnectionAlive(1000))
                        {
                            //If the existing connection comes back as alive we don‘t allow this one to go any further
                            //This might happen if two peers try to connect to each other at the same time
                            //如果连接已经存在  则连接创建异常
                            connectionSetupException = true;
                            connectionSetupExceptionStr = " ... existing live connection at provided end point for this connection (" + ConnectionInfo + "), there should be no need for a second.";
                        }
                    }

                    //We only try again if we did not log an exception
                    //我们再试一次,如果我们没有记录到异常
                    if (!connectionSetupException)
                    {
                        //Once we have tried to sort the problem we can try to finish the establish one last time
                        //一旦我们尝试解决这个问题 我们可以最后一次尝试去完成连接的创建
                        connectionEstablishedSuccess = ConnectionSetupHandlerFinal(remoteConnectionInfo, ref possibleClashWithExistingConnection, ref existingConnection);

                        //If we still failed then that‘s it for this establish
                        //尝试依然失败
                        if (!connectionEstablishedSuccess && !connectionSetupException)
                        {
                            connectionSetupException = true;
                            connectionSetupExceptionStr = "Attempted to establish connection with " + ConnectionInfo + ", but due to an existing connection this was not possible.";
                        }
                    }
                }

                //If we are server side and we receive a successful connection setup we can respond to here
                //如果我们是服务器端并且我们收到一个成功的连接设置,我们可以在此处进行回复
                if (connectionEstablishedSuccess && ConnectionInfo.ServerSide)
                    SendObject(Enum.GetName(typeof(ReservedPacketType), ReservedPacketType.ConnectionSetup), new ConnectionInfo(ConnectionInfo.ConnectionType, NetworkComms.NetworkIdentifier, ConnectionInfo.LocalEndPoint, true), NetworkComms.InternalFixedSendReceiveOptions);
            }

            //Trigger any setup waits
            //给予信号   触发任何等待设置
            connectionSetupWait.Set();
        }

        /// <summary>
        /// Attempts to complete the connection establish with a minimum of locking to avoid possible deadlocking
        /// 试图完成连接的创建使用一个最小所来避免可能的冲突
        /// </summary>
        /// <param name="remoteConnectionInfo">远端点连接信息对象  <see cref="ConnectionInfo"/> corresponding with remoteEndPoint</param>
        /// <param name="possibleClashWithExistingConnection">True if a connection already exists with provided remoteEndPoint</param>
        /// <param name="existingConnection">A reference to an existing connection if it exists</param>
        /// <returns>True if connection is successfully setup, otherwise false</returns>
        private bool ConnectionSetupHandlerFinal(ConnectionInfo remoteConnectionInfo, ref bool possibleClashWithExistingConnection, ref Connection existingConnection)
        {
            lock (NetworkComms.globalDictAndDelegateLocker)
            {
                List<Connection> connectionByEndPoint = NetworkComms.GetExistingConnection(ConnectionInfo.RemoteEndPoint, ConnectionInfo.LocalEndPoint, ConnectionInfo.ConnectionType, ConnectionInfo.ApplicationLayerProtocol);

                //If we no longer have the original endPoint reference (set in the constructor) then the connection must have been closed already
                //如果我们没有原始端点引用  然后连接必须已经被关闭
                if (connectionByEndPoint.Count == 0)
                {
                    connectionSetupException = true;
                    connectionSetupExceptionStr = "Connection setup received after connection closure with " + ConnectionInfo;
                }
                else
                {
                    //COMMENT: As of version 3.0.0 we have allowed loop back connections where the identifier is the same
                    //在3.0版本中 我们允许环回连接标识符是相同的
                    //We need to check for a possible GUID clash  我们需要检查一个可能的GUID冲突
                    //Probability of a clash is approx 0.1% if 1E19 connections are maintained simultaneously (This many connections has not be tested ;))
                    //可能出现冲突 概率为 0.1%  如果同时保持1e19次方 连接
                    //but hey, we live in a crazy world!  但是,嘿,我们生活在一个疯狂的世界
                    //if (remoteConnectionInfo.NetworkIdentifier == NetworkComms.NetworkIdentifier)
                    //{
                    //    connectionSetupException = true;
                    //    connectionSetupExceptionStr = "Remote peer has same network identifier to local, " + remoteConnectionInfo.NetworkIdentifier + ". A real duplication is vanishingly improbable so this exception has probably been thrown because the local and remote application are the same.";
                    //}
                    //else
                    if (connectionByEndPoint[0] != this)
                    {
                        possibleClashWithExistingConnection = true;
                        existingConnection = connectionByEndPoint[0];
                    }
                    else if (connectionByEndPoint[0].ConnectionInfo.NetworkIdentifier != ShortGuid.Empty &&
                        connectionByEndPoint[0].ConnectionInfo.NetworkIdentifier != remoteConnectionInfo.NetworkIdentifier)
                    {
                        //We are in the same connection, so don‘t need to throw and exception but the remote network identifier
                        //has changed.
                        //我们在同一个连接,所以不需要抛弃和异常但远程网络标识符已经改变。
                        //This can happen for connection types where the local connection (this) may not have been closed
                        //这可能发生  由于本地连接没有关闭
                        //when the remote peer closed. We need to trigger the connection close delegates with the old info, update
                        //the connection info and then call the establish delegates
                        //远程连接关闭时,我们需要触发连接的关闭委托,更新连接信息 然后调用创建委托
                        #region Reset Connection without closing
                        //Call the connection close delegates
                        try
                        {
                            //Almost there
                            //Last thing is to call any connection specific shutdown delegates
                            if (ConnectionSpecificShutdownDelegate != null)
                            {
                                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Triggered connection specific shutdown delegates with " + ConnectionInfo);
                                ConnectionSpecificShutdownDelegate(this);
                            }
                        }
                        catch (Exception ex)
                        {
                            LogTools.LogException(ex, "ConnectionSpecificShutdownDelegateError", "Error while executing connection specific shutdown delegates for " + ConnectionInfo + ". Ensure any shutdown exceptions are caught in your own code.");
                        }

                        try
                        {
                            //Last but not least we call any global connection shutdown delegates
                            if (NetworkComms.globalConnectionShutdownDelegates != null)
                            {
                                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Triggered global shutdown delegates with " + ConnectionInfo);
                                NetworkComms.globalConnectionShutdownDelegates(this);
                            }
                        }
                        catch (Exception ex)
                        {
                            LogTools.LogException(ex, "GlobalConnectionShutdownDelegateError", "Error while executing global connection shutdown delegates for " + ConnectionInfo + ". Ensure any shutdown exceptions are caught in your own code.");
                        }

                        EndPoint newRemoteEndPoint;
                        if (this.ConnectionInfo.RemoteEndPoint.GetType() == typeof(IPEndPoint) &&
                            remoteConnectionInfo.LocalEndPoint.GetType() == typeof(IPEndPoint))
                            newRemoteEndPoint = new IPEndPoint(this.ConnectionInfo.RemoteIPEndPoint.Address, remoteConnectionInfo.LocalIPEndPoint.Port);
                        else
                            throw new NotImplementedException("ConnectionSetupHandlerFinal not implemented for EndPoints of type " + this.ConnectionInfo.RemoteEndPoint.GetType());

                        NetworkComms.UpdateConnectionReferenceByEndPoint(this, newRemoteEndPoint, this.ConnectionInfo.LocalEndPoint);

                        ConnectionInfo.UpdateInfoAfterRemoteHandshake(remoteConnectionInfo, newRemoteEndPoint);

                        //Trigger the establish delegates
                        //出发创建委托
                        TriggerConnectionEstablishDelegates();
                        #endregion

                        return true;
                    }
                    else
                    {
                        //Update the connection info 更新连接信息
                        //We never change the this.ConnectionInfo.RemoteEndPoint.Address as there might be NAT involved
                        //我们不修改ConnnectionInfo.远端点    因为可能有NAT的参与
                        //We may update the port however 更新端口
                        EndPoint newRemoteEndPoint;
                        if (this is IPConnection)
                            newRemoteEndPoint = new IPEndPoint(this.ConnectionInfo.RemoteIPEndPoint.Address, remoteConnectionInfo.LocalIPEndPoint.Port);
#if NET35 || NET4
                        else if (this is BluetoothConnection)
                            newRemoteEndPoint = ConnectionInfo.RemoteBTEndPoint;
#endif
                        else
                            throw new NotImplementedException("ConnectionSetupHandlerFinal not implemented for EndPoints of type " + this.ConnectionInfo.RemoteEndPoint.GetType());

                        NetworkComms.UpdateConnectionReferenceByEndPoint(this, newRemoteEndPoint, this.ConnectionInfo.LocalEndPoint);

                        ConnectionInfo.UpdateInfoAfterRemoteHandshake(remoteConnectionInfo, newRemoteEndPoint);

                        return true;
                    }
                }
            }

            return false;
        }

        /// <summary>
        /// Returns ConnectionInfo.ToString
        /// 返回连接信息类的相关信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return ConnectionInfo.ToString();
        }
    }
时间: 2024-08-24 05:57:54

介绍开源的.net通信框架NetworkComms框架 源码分析(二十 )ConnectionCreate的相关文章

ABP源码分析二十六:核心框架中的一些其他功能

本文是ABP核心项目源码分析的最后一篇,介绍一些前面遗漏的功能 AbpSession AbpSession: 目前这个和CLR的Session没有什么直接的联系.当然可以自定义的去实现IAbpSession使之与CLR的Session关联 IAbpSession:定义如下图中的四个属性. NullAbpSession:IAbpSession的一个缺省实现,给每个属性都给予null值,无实际作用 ClaimsAbpSession:实现了从ClaimsPrincipal/ClaimsIdentity

缓存框架OSCache部分源码分析

在并发量比较大的场景,如果采用直接访问数据库的方式,将会对数据库带来巨大的压力,严重的情况下可能会导致数据库不可用状态,并且时间的消耗也是不能容忍的.在这种情况下,一般采用缓存的方式.将经常访问的热点数据提前加载到内存中,这样能够大大降低数据库的压力. OSCache是一个开源的缓存框架,虽然现在已经停止维护了,但是对于OSCache的实现还是值得学习和借鉴的.下面通过OSCache的部分源码分析OSCache的设计思想. 缓存数据结构 通常缓存都是通过<K,V>这种数据结构存储,但缓存都是应

android-----XUtils框架之HttpUtils源码分析

之前我们对Volley框架源码进行了分析,知道了他适用于频繁的网络请求,但是不太适合post较大数据以及文件的上传操作,在项目中为了弥补Volley的这个缺陷,使用了XUtils框架的HttpUtils实现了文件上传的操作,上一篇博客我们通过HttpUtils实现了照片上传的实例,见:android-----基于XUtils客户端以及服务器端实现,当然文件上传的方法类似于照片上传,有时间的话单独写一篇博客介绍,这篇博客我们从源码角度来分析HttpUtils的实现原理,希望对这几天的学习做个总结:

KopDB 框架学习2——源码分析

我的博客:http://mrfufufu.github.io/ 上次我们主要是对 KopDB 框架的使用进行了分析,它是非常简单有用的.这次主要是对它的源码进行分析,进一步的来了解它的真面目. 点击这里去往 "KopDB 框架学习1--使用" 因为 KopDB 采用的是对象关系映射(ORM)模式,即我们使用的编程语言是面向对象语言,而我们使用的数据库则是关系型数据库,那么将面向对象的语言和面向关系的数据库之间建立一种映射关系,这就是对象关系映射了. 使用 ORM 模式,主要是因为我们平

android-----XUtils框架之BitmapUtils源码分析

上一篇使用XUtils的BitmapUtils实现了一个照片墙的功能,参见:android-----XUtils框架之BitmapUtils加载照片实现,这一篇我们从源码的角度分析下BitmapUtils到底是怎么一个执行流程的: 先来回顾下之前我们使用BitmapUtils的步骤: 很简单,就只有两步: (1)通过BitmapUtils的构造函数创建对象: (2)调用BitmapUtils对象的display方法: 好了,我们先从创建BitmapUtils对象开始分析,很自然想到了Bitmap

首选项框架PreferenceFragment部分源码分析

因为要改一些settings里面的bug以及之前在里面有做过勿扰模式,准备对勿扰模式做一个总结,那先分析一下settings的源码,里面的核心应该就是android3.0 上面的首选项框架PreferenceFragment.因为在3.0之前都是把这些东西放在PreferenceActivity的,但是3.0之后google建议把setting放在PreferenceFragment,但是PreferenceActivity也同时在用的,下面就此总结一下: PreferenceActivity的

thinkphp5 源码分析二 框架引导

框架引导文件源代码 (/thinkphp/start.php) 1. 引入基础文件(/thinkphp/base.php) // 加载基础文件 require __DIR__ . '/base.php'; 基础文件(/thinkphp/base.php) 2. 定义系统常量 1 define('THINK_VERSION', '5.0.9'); 2 define('THINK_START_TIME', microtime(true)); 3 define('THINK_START_MEM', m

Java依赖注入库框架 Dagger的源码分析(一)

1.GeneratedAdapters 对应的注释上面是这么说的: A single point for API used in common by Adapters and Adapter generators 被Adapters以及Adapter的生产者广泛使用 通过代码,可以注意到,这是一个final类,是不允许被重载的. 他的构造函数是一个空的构造函数. 同时带有下面的常量的定义: private static final String SEPARATOR = "$$"; pu

Mahout协同过滤框架Taste的源码分析

推荐过程 主要分成了如下几步来完成推荐1. 输入数据预处理2. 获取评分矩阵3. 计算物品相似度4. 矩阵乘法5. 数据过滤6. 计算推荐 测试数据 user&item 1 2 3 4 5 1 3 3 3 2 0 2 4 4 4 0 0 3 5 5 5 0 3 4 4 4 4 1 4 继续阅读 →

Django框架——CBV及源码分析

CBV (基于类的视图函数) 代码示例: urls.py url(r'^login/',views.MyLogin.as_view()) views.py from django.views import View class MyLogin(View): def get(self,request): print("from MyLogin get方法") return render(request,'login.html') def post(self,request): retur