原文网址: 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");

                )
                    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();
                throw new ConnectionSetupException(e.ToString());
            }
            catch (Exception ex)
            {
                //If anything goes wrong we close the connection.
                //出现错误 关闭连接
                CloseConnection();

                //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, ));
#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 >  && // 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[]);

                //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 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
                //如果我们没有原始端点引用  然后连接必须已经被关闭
                )
                {
                    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
                    ] != this)
                    {
                        possibleClashWithExistingConnection = true;
                        existingConnection = connectionByEndPoint[];
                    }
                    ].ConnectionInfo.NetworkIdentifier != ShortGuid.Empty &&
                        connectionByEndPoint[].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();
        }
    }

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

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

    本文是ABP核心项目源码分析的最后一篇,介绍一些前面遗漏的功能 AbpSession AbpSession: 目前这个和CLR的Session没有什么直接的联系.当然可以自定义的去实现IAbpSess ...

  2. DotNetty网络通信框架学习之源码分析

    DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...

  3. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  4. 深入理解分布式调度框架TBSchedule及源码分析

    简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...

  5. 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)

    1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...

  6. 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)

    1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e,  要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...

  7. $Django cbv源码分析 djangorestframework框架之APIView源码分析

    1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...

  8. ④NuPlayer播放框架之Renderer源码分析

    [时间:2016-11] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,渲染器,render] 0 导读 之前我们分析了NuPlayer的实现代码,本文将重点聚 ...

  9. ⑤NuPlayer播放框架之GenericSource源码分析

    [时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...

  10. ③NuPlayer播放框架之类NuPlayer源码分析

    [时间:2016-10] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架] 0 引言 差不多一个月了,继续分析AOSP的播放框架的源码.这次我们需要深入分析的是N ...

随机推荐

  1. (小常识)Dictionary的遍历

                Dictionary<int, string> objDictionary = new Dictionary<int, string>();       ...

  2. JVM内存回收机制简述

    JVM内存回收机制涉及的知识点太多了,了解越多越迷糊,汗一个,这里仅简单做个笔记,主要参考<深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)> 目前java的jdk默认虚拟机为H ...

  3. 写js写傻了,明天研究一下异步

    在html某元素上绑定一个click事件,该事件是一个执行事件很长的函数,比如执行几十亿或几百亿次加法,那么在这个函数执行的过程中,其他元素绑定的事件,是如何触发的呢,异步触发还是同步,触发时是怎么执 ...

  4. Canvas 内部元素添加事件处理

    目录 前言 自定义事件 有序数组 元素父类 事件判断 其他 立即执行函数 apply, call, bind addEventListener 传参 调用父类的构造函数 对象检测 isPointInP ...

  5. 如何在 Ubuntu 15.04 上安装带 JSON 支持的 SQLite 3.9

    欢迎阅读我们关于SQLite 的文章,SQLite 是当今世界上使用最广泛的 SQL 数据库引擎,它基本不需要配置,不需要设置或管理就可以运行.SQLite 是一个是公开领域(public-domai ...

  6. ECMAScript5中数组的方法

    1.forEach()方法 遍历数组,为每个数组元素调用指定函数,三个参数分别为:数组元素 item.元素索引 index.数组本身 arr,无返回值 例: 2.map()方法 调用数组的每个元素传递 ...

  7. Atitit. Api 设计 原则 ---归一化

    Atitit. Api 设计 原则 ---归一化 1.1. 叫做归一化1 1.2. 归一化的实例:一切对象都可以序列化/toString  通过接口实现1 1.3. 泛文件概念.2 1.4. 游戏行业 ...

  8. js 字符串的操作

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  9. SQL SERVER 2005/2008 中关于架构的理解(二)

    本文上接SQL SERVER 2005/2008 中关于架构的理解(一)      架构的作用与示例 用户与架构(schema)分开,让数据库内各对象不再绑在某个用户账号上,可以解决SQL SERVE ...

  10. IOS-各控件默认尺寸和参考图标大小

    UITabBar