介绍开源的.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:
);
break;
case AddressFamily.InterNetworkV6:
);
break;
#if NET4 || NET35
:
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:
);
break;
case AddressFamily.InterNetworkV6:
);
break;
#if NET4 || NET35
:
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:
);
break;
case AddressFamily.InterNetworkV6:
);
break;
#if NET4 || NET35
:
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:
);
break;
case AddressFamily.InterNetworkV6:
);
break;
#if NET4 || NET35
:
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:
);
break;
case AddressFamily.InterNetworkV6:
);
break;
#if NET4 || NET35
:
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:
);
break;
case AddressFamily.InterNetworkV6:
);
break;
#if NET4 || NET35
:
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 ? << : );
if (RemoteEndPoint != null)
hashCodeCache = NetworkIdentifier.GetHashCode() ^ RemoteEndPoint.GetHashCode() ^ (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? << : );
else if (LocalEndPoint != null)
hashCodeCache = NetworkIdentifier.GetHashCode() ^ LocalEndPoint.GetHashCode() ^ (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? << : );
else
hashCodeCache = NetworkIdentifier.GetHashCode() ^ (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? << : );
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 = 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 = BitConverter.GetBytes((int)ConnectionType);
data.Add(conTypeData);
byte[] netIDData = Encoding.UTF8.GetBytes(NetworkIdentifierStr);
byte[] netIDLengthData = BitConverter.GetBytes(netIDData.Length);
data.Add(netIDLengthData);
data.Add(netIDData);
byte[] localEPAddreessData = Encoding.UTF8.GetBytes(localEndPointAddressStr);
byte[] localEPAddreessLengthData = BitConverter.GetBytes(localEPAddreessData.Length);
data.Add(localEPAddreessLengthData);
data.Add(localEPAddreessData);
byte[] localPortData = BitConverter.GetBytes(localEndPointPort);
data.Add(localPortData);
byte[] isConnectableData = BitConverter.GetBytes(IsConnectable);
data.Add(isConnectableData);
byte[] AppLayerEnabledData = BitConverter.GetBytes((int)ApplicationLayerProtocol);
data.Add(AppLayerEnabledData);
}
foreach (byte[] datum in data)
outputStream.Write(datum, , datum.Length);
}
/// <inheritdoc />
/// 反序列化 就是根据收到的内存流解析出ConnnectionInfo对象
public void Deserialize(System.IO.Stream inputStream)
{
, conTypeData.Length);
ConnectionType = (ConnectionType)BitConverter.ToInt32(conTypeData, );
, netIDLengthData.Length);
)]; inputStream.Read(netIDData, , netIDData.Length);
NetworkIdentifierStr = new String(Encoding.UTF8.GetChars(netIDData));
, sizeof(int));
)]; inputStream.Read(localEPAddreessData, , localEPAddreessData.Length);
localEndPointAddressStr = new String(Encoding.UTF8.GetChars(localEPAddreessData));
, sizeof(int));
localEndPointPort = BitConverter.ToInt32(localPortData, );
, sizeof(bool));
IsConnectable = BitConverter.ToBoolean(isConnectableData, );
, sizeof(int));
ApplicationLayerProtocol = (ApplicationLayerProtocolStatus)BitConverter.ToInt32(AppLayerEnabledData, );
#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的更多相关文章
- DotNetty网络通信框架学习之源码分析
DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...
- 框架-springmvc源码分析(二)
框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...
- 深入理解分布式调度框架TBSchedule及源码分析
简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...
- 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)
1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...
- 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)
1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e, 要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...
- $Django cbv源码分析 djangorestframework框架之APIView源码分析
1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...
- ABP源码分析二十六:核心框架中的一些其他功能
本文是ABP核心项目源码分析的最后一篇,介绍一些前面遗漏的功能 AbpSession AbpSession: 目前这个和CLR的Session没有什么直接的联系.当然可以自定义的去实现IAbpSess ...
- ④NuPlayer播放框架之Renderer源码分析
[时间:2016-11] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,渲染器,render] 0 导读 之前我们分析了NuPlayer的实现代码,本文将重点聚 ...
- ⑤NuPlayer播放框架之GenericSource源码分析
[时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...
- ③NuPlayer播放框架之类NuPlayer源码分析
[时间:2016-10] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架] 0 引言 差不多一个月了,继续分析AOSP的播放框架的源码.这次我们需要深入分析的是N ...
随机推荐
- Fatal error: Maximum function nesting level of '100' reached, aborting!
这个问题是由于启用了xdebug,而xdebug默认设置了函数最大嵌套数为100 解决办法: 找到php.ini文件,找到xdebug在最后加上xdebug.max_nesting_level = 5 ...
- Perl重命名当前目录下的文件
下载的zip包解压后,中文都变成了乱码,就写了个脚本重命名文件. use strict; use warnings; use Cwd; sub main { my $dir = getcwd(); o ...
- Atitit 记录方法调用参数上下文arguments
Atitit 记录方法调用参数上下文arguments 1.1. java java8 新的对象Parameter LocalVariableTable 本地变量表 MethodParamete ...
- 1027 HTML
body bgcolor(背景色)="#9900FF"(引号内呈现的是颜色代号,99是红色 00是绿色 FF是蓝色,所有颜色都是以这三个颜色调配) text (字体颜色)=&quo ...
- salesforce 零基础开发入门学习(十五)salesforce中formula的使用(不含Date/Time)
本文参考官方的formula介绍PDF:https://resources.docs.salesforce.com/200/latest/en-us/sfdc/pdf/salesforce_usefu ...
- Java-set集合
package exception; import java.util.Map; import java.util.TreeMap; import java.util.HashMap; public ...
- 第七节:Class与Style绑定
1.绑定class,v-bind:class 简写为::class 对象方式: <!-- 绑定一个class对象,也可以绑定data中的对象--> <span v-bind:cla ...
- 基于Rest服务实现的RPC
前言:现在RPC成熟的框架已经很多了,比喻Motan和Dubbo,但是今天我这里提供一种基于Rest服务的Rpc.和上一篇连着的http://www.cnblogs.com/LipeiNet/p/58 ...
- javascript技术大全
这更像是一篇为自己而写的文章,没有过多的解释,sorray. 关于:return function fn(num){ var a = num; if(a>1){ a = num + 1; ret ...
- Windows Server 2012 R2 里面如何安装Net Framework 3.5
图示 不要慌,和windows是不一样的,没有问题 下一步 默认即可,下一步 这里面的东西以后会装,先不管,我们今天目的是装 net framework 3.5 选一下 正在安装 如果出错了请参考: ...