介绍开源的.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 ...
随机推荐
- JS设置cookie、读取cookie、删除cookie
JS设置cookie.读取cookie.删除cookie JS设置cookie,注意一定要path=/ ,根目录,不然其他目录可能查询不到..默认是本目录. document.cookie ...
- Atitit 团队建设的知识管理
Atitit 团队建设的知识管理 1.1. 要遵循"知识积累--创造--应用--形成知识平台--再积累--再创造--再应用--形成新的知识平台"的循环过程.1 1.2. 显性知识包 ...
- Ajax技术
1.ajax技术的背景 不可否认,ajax技术的流行得益于google的大力推广,正是由于google earth.google suggest以及gmail等对ajax技术的广泛应用,催生了ajax ...
- fir.im Weekly - 如何打造真正的工程师文化
好的工程师,无法忍受低效且无趣的工作.优秀的技术团队应该自上而下的地推进技术平台化建设.DevOps.自动化构建.测试和部署流程,积极采用合适的第三方工具或创造工具,进行周期性的前沿技术分享等等. 先 ...
- 学习ASP.NET MVC(一)——我的第一个ASP.NET MVC应用程序
学习ASP.NET MVC系列: 学习ASP.NET MVC(一)——我的第一个ASP.NET MVC应用程序 学习ASP.NET MVC(二)——我的第一个ASP.NET MVC 控制器 学习ASP ...
- python导入模块和包的使用
做项目的时候经常会要求做到模块化管理,即同样功能的代码放到同一个文件夹下,以便于方便管理,相信很多人对模块的引用都模糊不清,今天鄙人在这里就总结下. 一.模块导入的使用 在同一个文件夹下有两个文件分别 ...
- Android入门(十)SQLite创建升级数据库
原文链接:http://www.orlion.ga/603/ 一.创建数据库 Android为了让我们能够更加方便地管理数据库,专门提供了一个 SQLiteOpenHelper帮助类, 借助这个类就可 ...
- heroku部署java web项目
一.开发 在本地eclipse创建maven web项目(此时可以当成正常的javaweb项目开发即可.注意添加servlet依赖,此时不用添加jetty依赖) 二.部署前准备 1.首先在pom.xm ...
- Android二维码之创建
由于微信的推出二维码走进了我们的生活,并且越来越多的人们正在发挥着自己的想象力去使用它,来方便我们的生活,我曾经听说过一个笑话,当我们死后,墓碑上不再有墓志铭,而会出现一个记录你一生信息的二维码,当人 ...
- 【原创】C#搭建足球赛事资料库与预测平台(6) 赔率数据表设计2
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源C#彩票数据资料库系列文章总目录:[目录]C#搭建足球赛事资料库与预测平台与彩票数据分析目录 本篇文章开始将逐步介 ...