首页 > 代码库 > 介绍开源的.net通信框架NetworkComms框架 源码分析(二)ConnectionInfo

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

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

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

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

ConnectionInfo 是连接的信息类 用来存放连接类型(TCP,UDP),连接ID,创建连接时间,是否服务器端,本地地址,远端地址,最近通信时间,等信息的类

/// <summary>    /// Contains any information related to the configuration of a <see cref="Connection"/> object.    /// 连接信息类    包含一个连接的相关配置信息    /// </summary>    public class ConnectionInfo : IEquatable<ConnectionInfo>, IExplicitlySerialize    {        /// <summary>        /// The type of this connection        /// 连接类型  比如TCP或者UDP        /// </summary>        public ConnectionType ConnectionType { get; internal set; }        /// <summary>        /// We store our unique peer identifier as a string so that it can be easily serialised.        /// 网络ID        /// 每一个连接都有一个 ShortGuid类型的网络ID  此处把网络ID转化为字符类型了        /// </summary>        string NetworkIdentifierStr;        //有一些类不支持直接序列化 比如 Image,IPEndPoint 我们又希望传递其信息  要做一些变通        //image类一般我们把他转成字节数据再序列化        string localEndPointAddressStr; //Only set on serialise  序列化时设置         int localEndPointPort; //Only set on serialise  序列化时设置        bool hashCodeCacheSet = false;        int hashCodeCache;        /// <summary>        /// True if the <see cref="RemoteEndPoint"/> is connectable.        /// 是否可连接  True 代表可连接        /// </summary>        public bool IsConnectable { get; private set; }        /// <summary>        /// The DateTime corresponding to the creation time of this connection object        /// 连接创建时间        /// </summary>        public DateTime ConnectionCreationTime { get; protected set; }        /// <summary>        /// True if connection was originally established by remote        /// 是否为服务器端          /// </summary>        public bool ServerSide { get; internal set; }        /// <summary>        /// If this connection is <see cref="ServerSide"/> references the listener that was used.        /// 如果为服务器端  相关联的连接监听基类        /// </summary>        public ConnectionListenerBase ConnectionListener { get; internal set; }        /// <summary>        /// The DateTime corresponding to the creation time of this connection object        /// 连接创建完成时间        /// </summary>        public DateTime ConnectionEstablishedTime { get; private set; }        /// <summary>        /// The <see cref="EndPoint"/> corresponding to the local end of this connection.        /// 连接对应的本地端点        /// </summary>        public EndPoint LocalEndPoint { get; private set; }        /// <summary>        /// The <see cref="EndPoint"/> corresponding to the local end of this connection.        /// 连接对应的远程端点        /// </summary>        public EndPoint RemoteEndPoint { get; private set; }        /// <summary>        /// Describes the current state of the connection        /// 连接状态        /// </summary>        public ConnectionState ConnectionState { get; private set; }        /// <summary>        /// Returns the networkIdentifier of this peer as a ShortGuid. If the NetworkIdentifier has not yet been set returns ShortGuid.Empty.        /// 返回 ShortGuid类型的网络ID        /// </summary>        public ShortGuid NetworkIdentifier        {            get             {                if (NetworkIdentifierStr == null || NetworkIdentifierStr == "") return ShortGuid.Empty;                else return new ShortGuid(NetworkIdentifierStr);            }        }        DateTime lastTrafficTime;        object internalLocker = new object();        /// <summary>        /// The DateTime corresponding to the time data was sent or received        /// 连接上的数据最近的更新时间        /// </summary>        public DateTime LastTrafficTime        {            get            {                lock (internalLocker)                    return lastTrafficTime;            }            protected set            {                lock (internalLocker)                    lastTrafficTime = value;            }        }        /// <summary>        /// If enabled NetworkComms.Net uses a custom application layer protocol to provide         /// useful features such as inline serialisation, transparent packet transmission,         /// remote peer information etc. Default: ApplicationLayerProtocolStatus.Enabled        /// 应用层协议状态  默认启用  启用后可以使用networkcomms提供的内部序列化,透明数据包传送等功能        /// </summary>        public ApplicationLayerProtocolStatus ApplicationLayerProtocol { get; private set; }        #region Internal Usages        /// <summary>        /// The localEndPoint cast as <see cref="IPEndPoint"/>.        /// 本地端点        /// </summary>        internal IPEndPoint LocalIPEndPoint        {            get            {                try                {                    return (IPEndPoint)LocalEndPoint;                }                catch (InvalidCastException ex)                {                    throw new InvalidCastException("Unable to cast LocalEndPoint to IPEndPoint.", ex);                }            }        }        /// <summary>        /// The remoteEndPoint cast as <see cref="IPEndPoint"/>.        /// 远程端点        /// </summary>        internal IPEndPoint RemoteIPEndPoint        {            get            {                try                {                    return (IPEndPoint)RemoteEndPoint;                }                catch (InvalidCastException ex)                {                    throw new InvalidCastException("Unable to cast LocalEndPoint to IPEndPoint.", ex);                }            }        }#if NET4 || NET35        /// <summary>        /// The localEndPoint cast as <see cref="IPEndPoint"/>.        /// </summary>        internal BluetoothEndPoint LocalBTEndPoint        {            get            {                try                {                    return (BluetoothEndPoint)LocalEndPoint;                }                catch (InvalidCastException ex)                {                    throw new InvalidCastException("Unable to cast LocalEndPoint to IPEndPoint.", ex);                }            }        }        /// <summary>        /// The remoteEndPoint cast as <see cref="IPEndPoint"/>.        /// </summary>        internal BluetoothEndPoint RemoteBTEndPoint        {            get            {                try                {                    return (BluetoothEndPoint)RemoteEndPoint;                }                catch (InvalidCastException ex)                {                    throw new InvalidCastException("Unable to cast LocalEndPoint to IPEndPoint.", ex);                }            }        }#endif        #endregion        /// <summary>        /// Private constructor required for deserialisation.        /// 私有构造器   反序列化时需使用        /// </summary>#if ANDROID || iOS        [Preserve]#endif        private ConnectionInfo() { }        /// <summary>        /// Create a new ConnectionInfo object pointing at the provided remote <see cref="IPEndPoint"/>.        /// Uses the custom NetworkComms.Net application layer protocol.        /// 根据目标端点,创建一个连接对象 启用networkcomms.net应用层协议        /// </summary>        /// <param name="remoteEndPoint">The end point corresponding with the remote target</param>        public ConnectionInfo(EndPoint remoteEndPoint)        {            this.RemoteEndPoint = remoteEndPoint;                        switch (remoteEndPoint.AddressFamily)            {                case AddressFamily.InterNetwork:                    this.LocalEndPoint = new IPEndPoint(IPAddress.Any, 0);                    break;                case AddressFamily.InterNetworkV6:                    this.LocalEndPoint = new IPEndPoint(IPAddress.IPv6Any, 0);                    break;#if NET4 || NET35                case (AddressFamily)32:                    this.LocalEndPoint = new BluetoothEndPoint(BluetoothAddress.None, BluetoothService.SerialPort);                    break;#endif            }                        this.ConnectionCreationTime = DateTime.Now;            this.ApplicationLayerProtocol = ApplicationLayerProtocolStatus.Enabled;        }        /// <summary>        /// Create a new ConnectionInfo object pointing at the provided remote <see cref="IPEndPoint"/> 根据远程端点创建一个连接信息对象        /// </summary>        /// <param name="remoteEndPoint">The end point corresponding with the remote target  远程端点</param>        /// <param name="applicationLayerProtocol">If enabled NetworkComms.Net uses a custom         /// application layer protocol to provide useful features such as inline serialisation,         /// transparent packet transmission, remote peer handshake and information etc. We strongly         /// recommend you enable the NetworkComms.Net application layer protocol. 应用层协议(前面已介绍)</param>        public ConnectionInfo(EndPoint remoteEndPoint, ApplicationLayerProtocolStatus applicationLayerProtocol)        {            if (applicationLayerProtocol == ApplicationLayerProtocolStatus.Undefined)                throw new ArgumentException("A value of ApplicationLayerProtocolStatus.Undefined is invalid when creating instance of ConnectionInfo.", "applicationLayerProtocol");            this.RemoteEndPoint = remoteEndPoint;                        switch (remoteEndPoint.AddressFamily)            {                case AddressFamily.InterNetwork:                    this.LocalEndPoint = new IPEndPoint(IPAddress.Any, 0);                    break;                case AddressFamily.InterNetworkV6:                    this.LocalEndPoint = new IPEndPoint(IPAddress.IPv6Any, 0);                    break;#if NET4 || NET35                case (AddressFamily)32:                    this.LocalEndPoint = new BluetoothEndPoint(BluetoothAddress.None, BluetoothService.SerialPort);                    break;#endif            }            this.ConnectionCreationTime = DateTime.Now;            this.ApplicationLayerProtocol = applicationLayerProtocol;        }        /// <summary>        /// Create a new ConnectionInfo object pointing at the provided remote ipAddress and port.         /// Provided ipAddress and port are parsed in to <see cref="RemoteEndPoint"/>. Uses the         /// custom NetworkComms.Net application layer protocol.        /// 根据远程IP地址和端口号创建连接对象        /// </summary>        /// <param name="remoteIPAddress">IP地址  IP address of the remote target in string format, e.g. "192.168.0.1" </param>        /// <param name="remotePort">端口号   The available port of the remote target.          /// Valid ports are 1 through 65535. Port numbers less than 256 are reserved for well-known services (like HTTP on port 80) and port numbers less than 1024 generally require admin access</param>        public ConnectionInfo(string remoteIPAddress, int remotePort)        {            IPAddress ipAddress;            if (!IPAddress.TryParse(remoteIPAddress, out ipAddress))                throw new ArgumentException("Provided remoteIPAddress string was not successfully parsed.", "remoteIPAddress");            this.RemoteEndPoint = new IPEndPoint(ipAddress, remotePort);                        switch (this.RemoteEndPoint.AddressFamily)            {                case AddressFamily.InterNetwork:                    this.LocalEndPoint = new IPEndPoint(IPAddress.Any, 0);                    break;                case AddressFamily.InterNetworkV6:                    this.LocalEndPoint = new IPEndPoint(IPAddress.IPv6Any, 0);                    break;#if NET4 || NET35                case (AddressFamily)32:                    this.LocalEndPoint = new BluetoothEndPoint(BluetoothAddress.None, BluetoothService.SerialPort);                    break;#endif            }            this.ConnectionCreationTime = DateTime.Now;            this.ApplicationLayerProtocol = ApplicationLayerProtocolStatus.Enabled;        }        /// <summary>        /// Create a new ConnectionInfo object pointing at the provided remote ipAddress and port.         /// Provided ipAddress and port are parsed in to <see cref="RemoteEndPoint"/>.        /// 根据远程IP地址和端口号创建连接对象        /// </summary>        /// <param name="remoteIPAddress">IP地址   IP address of the remote target in string format, e.g. "192.168.0.1"</param>        /// <param name="remotePort">端口号      The available port of the remote target.         /// Valid ports are 1 through 65535. Port numbers less than 256 are reserved for well-known services (like HTTP on port 80) and port numbers less than 1024 generally require admin access</param>        /// <param name="applicationLayerProtocol">If enabled NetworkComms.Net uses a custom         /// application layer protocol to provide useful features such as inline serialisation,         /// transparent packet transmission, remote peer handshake and information etc. We strongly         /// recommend you enable the NetworkComms.Net application layer protocol.</param>        public ConnectionInfo(string remoteIPAddress, int remotePort, ApplicationLayerProtocolStatus applicationLayerProtocol)        {            if (applicationLayerProtocol == ApplicationLayerProtocolStatus.Undefined)                throw new ArgumentException("A value of ApplicationLayerProtocolStatus.Undefined is invalid when creating instance of ConnectionInfo.", "applicationLayerProtocol");            IPAddress ipAddress;            if (!IPAddress.TryParse(remoteIPAddress, out ipAddress))                throw new ArgumentException("Provided remoteIPAddress string was not successfully parsed.", "remoteIPAddress");            this.RemoteEndPoint = new IPEndPoint(ipAddress, remotePort);                        switch (this.RemoteEndPoint.AddressFamily)            {                case AddressFamily.InterNetwork:                    this.LocalEndPoint = new IPEndPoint(IPAddress.Any, 0);                    break;                case AddressFamily.InterNetworkV6:                    this.LocalEndPoint = new IPEndPoint(IPAddress.IPv6Any, 0);                    break;#if NET4 || NET35                case (AddressFamily)32:                    this.LocalEndPoint = new BluetoothEndPoint(BluetoothAddress.None, BluetoothService.SerialPort);                    break;#endif            }            this.ConnectionCreationTime = DateTime.Now;            this.ApplicationLayerProtocol = applicationLayerProtocol;        }        /// <summary>        /// Create a connectionInfo object which can be used to inform a remote peer of local connectivity.        /// Uses the custom NetworkComms.Net application layer protocol.        /// 创建一个连接对象  设定了本地端点   可用于与远程端点进行连接        /// 启用了自定义应用层协议        /// </summary>        /// <param name="connectionType">连接类型  The type of connection</param>        /// <param name="localNetworkIdentifier">本地网络ID   The local network identifier</param>        /// <param name="localEndPoint">本地端点   The localEndPoint which should be referenced remotely</param>        /// <param name="isConnectable">是否可连接   True if connectable on provided localEndPoint</param>        public ConnectionInfo(ConnectionType connectionType, ShortGuid localNetworkIdentifier, EndPoint localEndPoint, bool isConnectable)        {            if (localEndPoint == null)                throw new ArgumentNullException("localEndPoint", "localEndPoint may not be null");            this.ConnectionType = connectionType;            this.NetworkIdentifierStr = localNetworkIdentifier.ToString();            switch (localEndPoint.AddressFamily)            {                case AddressFamily.InterNetwork:                    this.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);                    break;                case AddressFamily.InterNetworkV6:                    this.RemoteEndPoint = new IPEndPoint(IPAddress.IPv6Any, 0);                    break;#if NET4 || NET35                case (AddressFamily)32:                    this.RemoteEndPoint = new BluetoothEndPoint(BluetoothAddress.None, BluetoothService.SerialPort);                    break;#endif            }            this.LocalEndPoint = localEndPoint;            this.IsConnectable = isConnectable;            this.ApplicationLayerProtocol = ApplicationLayerProtocolStatus.Enabled;        }        /// <summary>        /// Create a connectionInfo object which can be used to inform a remote peer of local connectivity        /// 创建一个连接对象  设定了本地端点   可用于与远程端点进行连接        /// </summary>        /// <param name="connectionType">连接类型  The type of connection</param>        /// <param name="localNetworkIdentifier">本地网络ID   The local network identifier</param>        /// <param name="localEndPoint">本地端点   The localEndPoint which should be referenced remotely</param>        /// <param name="isConnectable">是否可连接   True if connectable on provided localEndPoint</param>        /// <param name="applicationLayerProtocol">应用层协议  If enabled NetworkComms.Net uses a custom         /// application layer protocol to provide useful features such as inline serialisation,         /// transparent packet transmission, remote peer handshake and information etc. We strongly         /// recommend you enable the NetworkComms.Net application layer protocol.</param>        public ConnectionInfo(ConnectionType connectionType, ShortGuid localNetworkIdentifier, EndPoint localEndPoint, bool isConnectable, ApplicationLayerProtocolStatus applicationLayerProtocol)        {            if (localEndPoint == null)                throw new ArgumentNullException("localEndPoint", "localEndPoint may not be null");            if (applicationLayerProtocol == ApplicationLayerProtocolStatus.Undefined)                throw new ArgumentException("A value of ApplicationLayerProtocolStatus.Undefined is invalid when creating instance of ConnectionInfo.", "applicationLayerProtocol");            this.ConnectionType = connectionType;            this.NetworkIdentifierStr = localNetworkIdentifier.ToString();            this.LocalEndPoint = localEndPoint;            switch (localEndPoint.AddressFamily)            {                case AddressFamily.InterNetwork:                    this.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);                    break;                case AddressFamily.InterNetworkV6:                    this.RemoteEndPoint = new IPEndPoint(IPAddress.IPv6Any, 0);                    break;#if NET4 || NET35                case (AddressFamily)32:                    this.RemoteEndPoint = new BluetoothEndPoint(BluetoothAddress.None, BluetoothService.SerialPort);                    break;#endif            }            this.IsConnectable = isConnectable;            this.ApplicationLayerProtocol = applicationLayerProtocol;        }        /// <summary>        /// Create a connectionInfo object for a new connection.        /// 为新的连接创建一个连接对象        /// </summary>        /// <param name="connectionType">连接类型  The type of connection</param>        /// <param name="remoteEndPoint">远端点    The remoteEndPoint of this connection</param>        /// <param name="localEndPoint">本地端点  The localEndpoint of this connection</param>        /// <param name="applicationLayerProtocol">应用层协议    If enabled NetworkComms.Net uses a custom         /// application layer protocol to provide useful features such as inline serialisation,         /// transparent packet transmission, remote peer handshake and information etc. We strongly         /// recommend you enable the NetworkComms.Net application layer protocol.</param>        /// <param name="connectionListener">The listener associated with this connection if server side</param>        internal ConnectionInfo(ConnectionType connectionType, EndPoint remoteEndPoint, EndPoint localEndPoint,             ApplicationLayerProtocolStatus applicationLayerProtocol = ApplicationLayerProtocolStatus.Enabled,             ConnectionListenerBase connectionListener = null)        {            if (localEndPoint == null)                throw new ArgumentNullException("localEndPoint", "localEndPoint may not be null");            if (remoteEndPoint == null)                throw new ArgumentNullException("remoteEndPoint", "remoteEndPoint may not be null");            if (applicationLayerProtocol == ApplicationLayerProtocolStatus.Undefined)                throw new ArgumentException("A value of ApplicationLayerProtocolStatus.Undefined is invalid when creating instance of ConnectionInfo.", "applicationLayerProtocol");            this.ServerSide = (connectionListener!=null);            this.ConnectionListener = connectionListener;            this.ConnectionType = connectionType;            this.RemoteEndPoint = remoteEndPoint;            this.LocalEndPoint = localEndPoint;            this.ConnectionCreationTime = DateTime.Now;            this.ApplicationLayerProtocol = applicationLayerProtocol;        }                /// <summary>        /// Marks the connection as establishing        /// 标记连接在创建中        /// </summary>        internal void NoteStartConnectionEstablish()        {            lock(internalLocker)            {                if (ConnectionState == ConnectionState.Shutdown) throw new ConnectionSetupException("Unable to mark as establishing as connection has already shutdown.");                if (ConnectionState == ConnectionState.Establishing) throw new ConnectionSetupException("Connection already marked as establishing");                else ConnectionState = ConnectionState.Establishing;            }        }        /// <summary>        /// Set this connectionInfo as established.        /// 设置连接信息类中连接状态为已经创建        /// </summary>        internal void NoteCompleteConnectionEstablish()        {            lock (internalLocker)            {                if (ConnectionState == ConnectionState.Shutdown) throw new ConnectionSetupException("Unable to mark as established as connection has already shutdown.");                if (!(ConnectionState == ConnectionState.Establishing)) throw new ConnectionSetupException("Connection should be marked as establishing before calling CompleteConnectionEstablish");                if (ConnectionState == ConnectionState.Established) throw new ConnectionSetupException("Connection already marked as established.");                ConnectionState = ConnectionState.Established;                ConnectionEstablishedTime = DateTime.Now;                //The below only really applied to TCP connections  以下只适用于TCP连接                //We only expect a remote network identifier for managed connections 我们希望使用远程网络ID来管理连接                //if (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled && NetworkIdentifier == ShortGuid.Empty)                //    throw new ConnectionSetupException("Remote network identifier should have been set by this point.");            }        }        /// <summary>        /// Note this connection as shutdown        /// 标记连接已经关闭        /// </summary>        internal void NoteConnectionShutdown()        {            lock (internalLocker)                ConnectionState = ConnectionState.Shutdown;        }        /// <summary>        /// Update the localEndPoint information for this connection        /// 更新本地端点        /// </summary>        /// <param name="localEndPoint"></param>        internal void UpdateLocalEndPointInfo(EndPoint localEndPoint)        {            if (localEndPoint == null)                throw new ArgumentNullException("localEndPoint", "localEndPoint may not be null.");            lock (internalLocker)            {                hashCodeCacheSet = false;                this.LocalEndPoint = localEndPoint;            }        }        /// <summary>        /// During a connection handShake we might be provided with more update information regarding endPoints, connectability and identifiers        /// 当连接握手时 我们提供更多的更新信息 比如 端点  可连接性  和网络ID        /// </summary>        /// <param name="handshakeInfo"><see cref="ConnectionInfo"/> provided by remoteEndPoint during connection handshake.  在连接握手时,远端点提供的连接信息类</param>        /// <param name="remoteEndPoint">The correct remoteEndPoint of this connection.  远端点</param>        internal void UpdateInfoAfterRemoteHandshake(ConnectionInfo handshakeInfo, EndPoint remoteEndPoint)        {            lock (internalLocker)            {                NetworkIdentifierStr = handshakeInfo.NetworkIdentifier.ToString();                RemoteEndPoint = remoteEndPoint;                //Not sure what this section was supposed to do  不确定这段是否可行                //For now we will uncomment and see if there was a reason during testing  根据测试 取消以下代码 因为其会带来一些bug                //It certainly creates a bug at the moment                //if (LocalEndPoint.GetType() == typeof(IPEndPoint) && handshakeInfo.LocalEndPoint.GetType() == typeof(IPEndPoint))                //    ((IPEndPoint)LocalEndPoint).Address = ((IPEndPoint)handshakeInfo.LocalEndPoint).Address;                //else                //    throw new NotImplementedException("UpdateInfoAfterRemoteHandshake not implemented for EndPoints of type " + LocalEndPoint.GetType());                IsConnectable = handshakeInfo.IsConnectable;            }        }        /// <summary>        /// Updates the last traffic time for this connection        /// 更新连接的最近传输时间        /// </summary>        internal void UpdateLastTrafficTime()        {            lock (internalLocker)                lastTrafficTime = DateTime.Now;        }        /// <summary>        /// Replaces the current networkIdentifier with that provided        /// 替换网络ID        /// </summary>        /// <param name="networkIdentifier">The new networkIdentifier for this connectionInfo  新的网络ID</param>        public void ResetNetworkIdentifer(ShortGuid networkIdentifier)        {            NetworkIdentifierStr = networkIdentifier.ToString();        }        /// <summary>        /// A connectionInfo object may be used across multiple connection sessions, i.e. due to a possible timeout.          /// This method resets the state of the connectionInfo object so that it may be reused.        /// 一个连接对象可以被多个连接会话使用  由于超时问题的存在        /// 此方法重置连接对象的状态使其可以被重新使用        /// </summary>        internal void ResetConnectionInfo()        {            lock (internalLocker)            {                ConnectionState = ConnectionState.Undefined;            }        }        /// <summary>        /// Compares this <see cref="ConnectionInfo"/> object with obj and returns true if obj is ConnectionInfo and both         /// the <see cref="NetworkIdentifier"/> and <see cref="RemoteEndPoint"/> match.        /// 比较参数中的连接对象是否与当前连接对象相等        /// </summary>        /// <param name="obj">The object to test of equality  测试相等的对象</param>        /// <returns></returns>        public override bool Equals(object obj)        {            lock (internalLocker)            {                var other = obj as ConnectionInfo;                if (((object)other) == null)                    return false;                else                    return this == other;            }        }        /// <summary>        /// Compares this <see cref="ConnectionInfo"/> object with other and returns true if both the <see cref="NetworkIdentifier"/>         /// and <see cref="RemoteEndPoint"/> match.        /// 比较参数中的对象是否与当前连接对象相等        /// </summary>        /// <param name="other"></param>        /// <returns></returns>        public bool Equals(ConnectionInfo other)        {            lock (internalLocker)                return this == other;        }        /// <summary>        /// Returns left.Equals(right)        /// 返回 left.Equals(right)        /// </summary>        /// <param name="left">左侧的连接对象 Left connectionInfo</param>        /// <param name="right">右侧的连接对象  Right connectionInfo</param>        /// <returns> 如果相等返回True   True if both are equal, otherwise false</returns>        public static bool operator ==(ConnectionInfo left, ConnectionInfo right)        {            if (((object)left) == ((object)right)) return true;            else if (((object)left) == null || ((object)right) == null) return false;            else            {                if (left.RemoteEndPoint != null && right.RemoteEndPoint != null && left.LocalEndPoint != null && right.LocalEndPoint != null)                    return (left.NetworkIdentifier.ToString() == right.NetworkIdentifier.ToString() && left.RemoteEndPoint.Equals(right.RemoteEndPoint) && left.LocalEndPoint.Equals(right.LocalEndPoint) && left.ApplicationLayerProtocol == right.ApplicationLayerProtocol);                if (left.RemoteEndPoint != null && right.RemoteEndPoint != null)                    return (left.NetworkIdentifier.ToString() == right.NetworkIdentifier.ToString() && left.RemoteEndPoint.Equals(right.RemoteEndPoint) && left.ApplicationLayerProtocol == right.ApplicationLayerProtocol);                else if (left.LocalEndPoint != null && right.LocalEndPoint != null)                    return (left.NetworkIdentifier.ToString() == right.NetworkIdentifier.ToString() && left.LocalEndPoint.Equals(right.LocalEndPoint) && left.ApplicationLayerProtocol == right.ApplicationLayerProtocol);                else                    return (left.NetworkIdentifier.ToString() == right.NetworkIdentifier.ToString() && left.ApplicationLayerProtocol==right.ApplicationLayerProtocol);            }        }        /// <summary>        /// Returns !left.Equals(right)        /// 返回连接对象是否不相等        /// </summary>        /// <param name="left">Left connectionInfo</param>        /// <param name="right">Right connectionInfo</param>        /// <returns>True if both are different, otherwise false</returns>        public static bool operator !=(ConnectionInfo left, ConnectionInfo right)        {            return !(left == right);        }        /// <summary>        /// Returns NetworkIdentifier.GetHashCode() ^ RemoteEndPoint.GetHashCode();        /// 返回哈希码        /// </summary>        /// <returns>The hashcode for this connection info</returns>        public override int GetHashCode()        {            lock (internalLocker)            {                if (!hashCodeCacheSet)                {                    if (RemoteEndPoint != null & LocalEndPoint != null)                        hashCodeCache = NetworkIdentifier.GetHashCode() ^ LocalEndPoint.GetHashCode() ^ RemoteEndPoint.GetHashCode() ^ (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? 1 << 31 : 0);                    if (RemoteEndPoint != null)                        hashCodeCache = NetworkIdentifier.GetHashCode() ^ RemoteEndPoint.GetHashCode() ^ (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? 1 << 31 : 0);                    else if (LocalEndPoint != null)                        hashCodeCache = NetworkIdentifier.GetHashCode() ^ LocalEndPoint.GetHashCode() ^ (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? 1 << 31 : 0);                    else                        hashCodeCache = NetworkIdentifier.GetHashCode() ^ (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? 1 << 31 : 0);                    hashCodeCacheSet = true;                }                return hashCodeCache;            }        }        /// <summary>        /// Returns a string containing suitable information about this connection        /// 返回一个字符串  包含连接的状态信息        /// </summary>        /// <returns>A string containing suitable information about this connection</returns>        public override string ToString()        {            //Add a useful connection state identifier            //添加一个有用的连接状态ID            string connectionStateIdentifier;            switch (ConnectionState)            {                case ConnectionState.Undefined:                    connectionStateIdentifier = "U";                    break;                case ConnectionState.Establishing:                    connectionStateIdentifier = "I";                    break;                case ConnectionState.Established:                    connectionStateIdentifier = "E";                    break;                case ConnectionState.Shutdown:                    connectionStateIdentifier = "S";                    break;                default:                    throw new Exception("Unexpected connection state.");            }            string returnString = "[" + ConnectionType.ToString() + "-" + (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? "E" : "D") + "-" + connectionStateIdentifier + "] ";            if (RemoteEndPoint != null && LocalEndPoint != null)                returnString += LocalEndPoint.ToString() + " -> " + RemoteEndPoint.ToString();            else if (RemoteEndPoint != null)                returnString += "Local -> " + RemoteEndPoint.ToString();            else if (LocalEndPoint != null)                returnString += LocalEndPoint.ToString() + " " + (IsConnectable ? "Connectable" : "NotConnectable");            if (NetworkIdentifier != ShortGuid.Empty)                returnString += " (" + NetworkIdentifier + ")";            return returnString.Trim();        }        #region IExplicitlySerialize Members        /// <inheritdoc />        /// 序列化ConnectionInfo  V3版本在networkcomms的内核部分没有使用protobuf.net进行序列化          /// 这样使得基于networkcomms的程序可以很方便的更换序列化器.        /// 把ConnectionInfo对象转化为二进制字节数据        public void Serialize(Stream outputStream)        {            List<byte[]> data = http://www.mamicode.com/new List<byte[]>();            lock (internalLocker)            {                if (LocalEndPoint as IPEndPoint != null)                {                    localEndPointAddressStr = LocalIPEndPoint.Address.ToString();                    localEndPointPort = LocalIPEndPoint.Port;                }#if NET4 || NET35                if (LocalEndPoint as InTheHand.Net.BluetoothEndPoint != null)                {                    localEndPointAddressStr = LocalBTEndPoint.Address.ToString();                    localEndPointPort = LocalBTEndPoint.Port;                }#endif                byte[] conTypeData = http://www.mamicode.com/BitConverter.GetBytes((int)ConnectionType);                data.Add(conTypeData);                byte[] netIDData =http://www.mamicode.com/ Encoding.UTF8.GetBytes(NetworkIdentifierStr);                byte[] netIDLengthData =http://www.mamicode.com/ BitConverter.GetBytes(netIDData.Length);                data.Add(netIDLengthData);                data.Add(netIDData);                byte[] localEPAddreessData =http://www.mamicode.com/ Encoding.UTF8.GetBytes(localEndPointAddressStr);                byte[] localEPAddreessLengthData =http://www.mamicode.com/ BitConverter.GetBytes(localEPAddreessData.Length);                data.Add(localEPAddreessLengthData);                data.Add(localEPAddreessData);                byte[] localPortData =http://www.mamicode.com/ BitConverter.GetBytes(localEndPointPort);                data.Add(localPortData);                byte[] isConnectableData =http://www.mamicode.com/ BitConverter.GetBytes(IsConnectable);                data.Add(isConnectableData);                byte[] AppLayerEnabledData = http://www.mamicode.com/BitConverter.GetBytes((int)ApplicationLayerProtocol);                data.Add(AppLayerEnabledData);            }            foreach (byte[] datum in data)                outputStream.Write(datum, 0, datum.Length);                    }        /// <inheritdoc />        /// 反序列化   就是根据收到的内存流解析出ConnnectionInfo对象        public void Deserialize(System.IO.Stream inputStream)        {            byte[] conTypeData = http://www.mamicode.com/new byte[sizeof(int)]; inputStream.Read(conTypeData, 0, conTypeData.Length);                         ConnectionType = (ConnectionType)BitConverter.ToInt32(conTypeData, 0);                        byte[] netIDLengthData = http://www.mamicode.com/new byte[sizeof(int)]; inputStream.Read(netIDLengthData, 0, netIDLengthData.Length);            byte[] netIDData = http://www.mamicode.com/new byte[BitConverter.ToInt32(netIDLengthData, 0)]; inputStream.Read(netIDData, 0, netIDData.Length);                         NetworkIdentifierStr = new String(Encoding.UTF8.GetChars(netIDData));            byte[] localEPAddreessLengthData = http://www.mamicode.com/new byte[sizeof(int)]; inputStream.Read(localEPAddreessLengthData, 0, sizeof(int));            byte[] localEPAddreessData = http://www.mamicode.com/new byte[BitConverter.ToInt32(localEPAddreessLengthData, 0)]; inputStream.Read(localEPAddreessData, 0, localEPAddreessData.Length);                         localEndPointAddressStr = new String(Encoding.UTF8.GetChars(localEPAddreessData));            byte[] localPortData = http://www.mamicode.com/new byte[sizeof(int)]; inputStream.Read(localPortData, 0, sizeof(int));            localEndPointPort = BitConverter.ToInt32(localPortData, 0);            byte[] isConnectableData = http://www.mamicode.com/new byte[sizeof(int)]; inputStream.Read(isConnectableData, 0, sizeof(bool));                        IsConnectable = BitConverter.ToBoolean(isConnectableData, 0);            byte[] AppLayerEnabledData = http://www.mamicode.com/new byte[sizeof(int)]; inputStream.Read(AppLayerEnabledData, 0, sizeof(int));            ApplicationLayerProtocol = (ApplicationLayerProtocolStatus)BitConverter.ToInt32(AppLayerEnabledData, 0);            #if NET4 || NET35            if (ConnectionType == ConnectionType.Bluetooth)            {                BluetoothAddress btAddress;                if(!BluetoothAddress.TryParse(localEndPointAddressStr, out btAddress))                    throw new ArgumentException("Failed to parse BluetoothAddress from localEndPointAddressStr", "localEndPointAddressStr");                LocalEndPoint = new BluetoothEndPoint(btAddress, BluetoothService.SerialPort, localEndPointPort);                return;            }#endif            IPAddress ipAddress;            if (!IPAddress.TryParse(localEndPointAddressStr, out ipAddress))                throw new ArgumentException("Failed to parse IPAddress from localEndPointAddressStr", "localEndPointAddressStr");            LocalEndPoint = new IPEndPoint(ipAddress, localEndPointPort);        }        /// <summary>        /// Deserializes from a memory stream to a <see cref="ConnectionInfo"/> object        /// </summary>        /// <param name="ms">The memory stream containing the serialized <see cref="ConnectionInfo"/></param>        /// <param name="result">The deserialized <see cref="ConnectionInfo"/></param>        public static void Deserialize(MemoryStream ms, out ConnectionInfo result)        {            result = new ConnectionInfo();            result.Deserialize(ms);                    }        #endregion    }

 

该类实现了IExplicitlySerialize接口。

这是框架作者,从通讯内核中解耦protobuf序列化器所作的工作。实现了这个接口,可以使用显式的方法对ConnectionInfo类进行序列化,是的通信框架可以脱离Protobuf而进行工作。

当然,框架中还有一些别的类也需要实现这个接口。

 

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