如何检查TCP连接是否关闭,占IPV6?
How to check if a TCP connection is closed, accounting for IPV6?
我已经使用 this code 检查 TCP 连接是否关闭。但是,在使用此代码时,我注意到如果连接使用 IPV4,它不适用于 IPV6 地址:
if (!socket.Connected) return false;
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
var tcpConnections = ipProperties.GetActiveTcpConnections()
.Where(x => x.LocalEndPoint.Equals(socket.LocalEndPoint) && x.RemoteEndPoint.Equals(socket.RemoteEndPoint));
var isConnected = false;
if (tcpConnections != null && tcpConnections.Any())
{
TcpState stateOfConnection = tcpConnections.First().State;
if (stateOfConnection == TcpState.Established)
{
isConnected = true;
}
}
return isConnected;
在调试链接答案中的代码时,我注意到 returns 一个包含以下端点的列表:
{127.0.0.1:50503}
但是我正在测试的套接字似乎是 IPV6:
{[::ffff:127.0.0.1]:50503}
{127.0.0.1:50503} == {[::ffff:127.0.0.1]:50503}
returns false,所以检查失败。
如何测试 IPV4 地址和 IPV6 地址是否指向同一主机?
我最终创建了一个检查,如果另一端是 IPV6,它会将端点“提升”到 IPV6:
public static bool IsConnectionEstablished(this Socket socket)
{
if (socket is null)
{
throw new ArgumentNullException(nameof(socket));
}
if (!socket.Connected) return false;
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
var tcpConnections = ipProperties.GetActiveTcpConnections()
.Where(x => x.LocalEndPoint is IPEndPoint && x.RemoteEndPoint is IPEndPoint && x.LocalEndPoint != null && x.RemoteEndPoint != null)
.Where(x => AreEndpointsEqual(x.LocalEndPoint, (IPEndPoint)socket.LocalEndPoint!) && AreEndpointsEqual(x.RemoteEndPoint, (IPEndPoint)socket.RemoteEndPoint!));
var isConnected = false;
if (tcpConnections != null && tcpConnections.Any())
{
TcpState stateOfConnection = tcpConnections.First().State;
if (stateOfConnection == TcpState.Established)
{
isConnected = true;
}
}
return isConnected;
}
public static bool AreEndpointsEqual(IPEndPoint left, IPEndPoint right)
{
if (left.AddressFamily == AddressFamily.InterNetwork &&
right.AddressFamily == AddressFamily.InterNetworkV6)
{
left = new IPEndPoint(left.Address.MapToIPv6(), left.Port);
}
if (left.AddressFamily == AddressFamily.InterNetworkV6 &&
right.AddressFamily == AddressFamily.InterNetwork)
{
right = new IPEndPoint(right.Address.MapToIPv6(), right.Port);
}
return left.Equals(right);
}
我已经使用 this code 检查 TCP 连接是否关闭。但是,在使用此代码时,我注意到如果连接使用 IPV4,它不适用于 IPV6 地址:
if (!socket.Connected) return false;
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
var tcpConnections = ipProperties.GetActiveTcpConnections()
.Where(x => x.LocalEndPoint.Equals(socket.LocalEndPoint) && x.RemoteEndPoint.Equals(socket.RemoteEndPoint));
var isConnected = false;
if (tcpConnections != null && tcpConnections.Any())
{
TcpState stateOfConnection = tcpConnections.First().State;
if (stateOfConnection == TcpState.Established)
{
isConnected = true;
}
}
return isConnected;
在调试链接答案中的代码时,我注意到 returns 一个包含以下端点的列表:
{127.0.0.1:50503}
但是我正在测试的套接字似乎是 IPV6:
{[::ffff:127.0.0.1]:50503}
{127.0.0.1:50503} == {[::ffff:127.0.0.1]:50503}
returns false,所以检查失败。
如何测试 IPV4 地址和 IPV6 地址是否指向同一主机?
我最终创建了一个检查,如果另一端是 IPV6,它会将端点“提升”到 IPV6:
public static bool IsConnectionEstablished(this Socket socket)
{
if (socket is null)
{
throw new ArgumentNullException(nameof(socket));
}
if (!socket.Connected) return false;
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
var tcpConnections = ipProperties.GetActiveTcpConnections()
.Where(x => x.LocalEndPoint is IPEndPoint && x.RemoteEndPoint is IPEndPoint && x.LocalEndPoint != null && x.RemoteEndPoint != null)
.Where(x => AreEndpointsEqual(x.LocalEndPoint, (IPEndPoint)socket.LocalEndPoint!) && AreEndpointsEqual(x.RemoteEndPoint, (IPEndPoint)socket.RemoteEndPoint!));
var isConnected = false;
if (tcpConnections != null && tcpConnections.Any())
{
TcpState stateOfConnection = tcpConnections.First().State;
if (stateOfConnection == TcpState.Established)
{
isConnected = true;
}
}
return isConnected;
}
public static bool AreEndpointsEqual(IPEndPoint left, IPEndPoint right)
{
if (left.AddressFamily == AddressFamily.InterNetwork &&
right.AddressFamily == AddressFamily.InterNetworkV6)
{
left = new IPEndPoint(left.Address.MapToIPv6(), left.Port);
}
if (left.AddressFamily == AddressFamily.InterNetworkV6 &&
right.AddressFamily == AddressFamily.InterNetwork)
{
right = new IPEndPoint(right.Address.MapToIPv6(), right.Port);
}
return left.Equals(right);
}