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

Connection类之ConnectionCreate.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>        public ConnectionInfo ConnectionInfo { get; protected set; }                      /// 一个 manualResetEvent信号 用来处理连接的创建 setup                protected ManualResetEvent connectionSetupWait = new ManualResetEvent(false);        /// <summary>        /// 一个 manualResetEvent信号 用来处理连接的创建  establish.        /// </summary>        protected ManualResetEvent connectionEstablishWait = new ManualResetEvent(false);        /// <summary>         /// 连接创建是否异常        /// </summary>        protected bool connectionSetupException = false;        /// <summary>        /// 连接床架异常相关的信息        /// </summary>        protected string connectionSetupExceptionStr = "";        /// <summary>        ///创建一个连接对象        /// </summary>        /// <param name="connectionInfo">连接信息类</param>        /// <param name="defaultSendReceiveOptions">默认的收发参数</param>        protected Connection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions)        {            //创建一个方差类 这个是数学模型            SendTimesMSPerKBCache = new CommsMath();            //默认的数据缓冲区大小            dataBuffer = new byte[NetworkComms.ReceiveBufferSizeBytes];            //实例化一个数据包创建器            //PacketBuilder用来保存连接上收到的二进制数据            //他的模型是这样的,连接上收到的第一个字节中的数据,对应的是数据包包头的长度,根据第一个字节中的数据,解析出数据包包头,            //然后根据数据包包头中的信息,信息包括数据包长度,再解析出数据包,然后把数据包交给相应的处理器进行处理            packetBuilder = new PacketBuilder();                    //初始化一个顺序号 之后每发送一个数据包顺序后都加1 所以没有包的顺序号都是唯一的            packetSequenceCounter = Interlocked.Increment(ref NetworkComms.totalPacketSendCount);            ConnectionInfo = connectionInfo;            if (defaultSendReceiveOptions != null)                ConnectionDefaultSendReceiveOptions = defaultSendReceiveOptions;            else                //如果没有默认的收发参数 则使用NetworkComms静态类中的默认收发参数                //默认收发参数使用protobuf作为序列化器,没有启用加密和压缩处理器                ConnectionDefaultSendReceiveOptions = NetworkComms.DefaultSendReceiveOptions;            if (NetworkComms.commsShutdown) throw new ConnectionSetupException("Attempting to create new connection after global comms 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.ConnectionType))                throw new ConnectionSetupException("A connection already exists with " + ConnectionInfo);            //添加连接到NetworkComms静态类中            //比如说服务器的话,会把监听到的连接都添加一个引用到NetworkComms静态类中            //如果某个连接断开了,networkComms静态类中,也会相应的删除这个连接。            NetworkComms.AddConnectionByReferenceEndPoint(this);        }        /// <summary>        ///创建这个连接        /// </summary>        public void EstablishConnection()        {            try            {                bool connectionAlreadyEstablishing = false;                lock (delegateLocker)                {                    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 succesfully established.");                }                else                {                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace("Establishing new connection with " + ConnectionInfo);                    //这是个virtual方法,具体工作交给子类去做,TCPConnection类负责建立Tcp连接 UDPConnection类负责建UDP连接                    EstablishConnectionSpecific();                    if (ConnectionInfo.ConnectionState == ConnectionState.Shutdown) throw new ConnectionSetupException("Connection was closed during establish handshake.");                    if (ConnectionInfo.NetworkIdentifier == ShortGuid.Empty)                        throw new ConnectionSetupException("Remote network identifier should have been set by this point.");                    //Once the above has been done the last step is to allow other threads to use the connection                    ConnectionInfo.NoteCompleteConnectionEstablish();                    NetworkComms.AddConnectionReferenceByIdentifier(this);                    connectionEstablishWait.Set();                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... connection succesfully 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. Base should be called to trigger connection establish delegates        /// </summary>        protected virtual void EstablishConnectionSpecific()        {            //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        /// </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 succesfully 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.");                return connectionSetupWait.WaitOne(waitTimeoutMS);            }        }        /// <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 possibleClashConnectionWithPeer_ByEndPoint = 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 possibleClashConnectionWithPeer_ByEndPoint, ref existingConnection);                //If we were not succesfull 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 (possibleClashConnectionWithPeer_ByEndPoint)                    {                        //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 possibleClashConnectionWithPeer_ByEndPoint, ref existingConnection);                        //If we still failed then that‘s it for this establish                        if (!connectionEstablishedSuccess && !connectionSetupException)                        {                            connectionSetupException = true;                            connectionSetupExceptionStr = "Attempted to establish conneciton with " + ConnectionInfo + ", but due to an existing connection this was not possible.";                        }                    }                }            }            //Trigger any setup waits            connectionSetupWait.Set();        }        /// <summary>        /// Attempts to complete the connection establish with a minimum of locking to prevent possible deadlocking        /// </summary>        /// <param name="remoteConnectionInfo"><see cref="ConnectionInfo"/> corresponding with remoteEndPoint</param>        /// <param name="possibleClashConnectionWithPeer_ByEndPoint">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 possibleClashConnectionWithPeer_ByEndPoint, ref Connection existingConnection)        {            lock (NetworkComms.globalDictAndDelegateLocker)            {                Connection connectionByEndPoint = NetworkComms.GetExistingConnection(ConnectionInfo.RemoteEndPoint, ConnectionInfo.ConnectionType);                //If we no longer have the original endPoint reference (set in the constructor) then the connection must have been closed already                if (connectionByEndPoint == null)                {                    connectionSetupException = true;                    connectionSetupExceptionStr = "Connection setup received after connection closure with " + ConnectionInfo;                }                else                {                    //We need to check for a possible GUID clash                    //Probability of a clash is approx 0.1% if 1E19 connection are maintained simultaneously (This many connections has not be tested ;))                    //but hey, we live in a crazy world!                    if (remoteConnectionInfo.NetworkIdentifier == NetworkComms.NetworkIdentifier)                    {                        connectionSetupException = true;                        connectionSetupExceptionStr = "Remote peer has same network idendifier 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 != this)                    {                        possibleClashConnectionWithPeer_ByEndPoint = true;                        existingConnection = connectionByEndPoint;                    }                    else                    {                        //Update the connection info                        //We never change the this.ConnectionInfo.RemoteEndPoint.Address as there might be NAT involved                        //We may update the port however                        IPEndPoint newRemoteIPEndPoint = new IPEndPoint(this.ConnectionInfo.RemoteEndPoint.Address, remoteConnectionInfo.LocalEndPoint.Port);                        NetworkComms.UpdateConnectionReferenceByEndPoint(this, newRemoteIPEndPoint);                        ConnectionInfo.UpdateInfoAfterRemoteHandshake(remoteConnectionInfo, newRemoteIPEndPoint);                        return true;                    }                }            }            return false;        }        /// <summary>        /// Returns ConnectionInfo.ToString        /// </summary>        /// <returns></returns>        public override string ToString()        {            return ConnectionInfo.ToString();        }    }}

 

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

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

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

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

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

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

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

 

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

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