注意本文实现的 “V6ToV4,V4ToV6” 是给操作系统用的,如 Linux/Windows,而不是搞特殊标准,即 “2001/2002” 开头的映射V6地址格式。
2001:IANA特殊地址 Teredo隧道地址。
2002:是V6转V4地址,由用户端设备自动建立,通过隧道技术连接至IPv6 互联网,不是运营商管理和分配的,服务质量与运营商无关。
话是这么说的,但实际上不是所有的运营商都按这个套路来的,有些需要加运营商给你的特殊IPV6前缀才能实现,IPV6访问IPV4资源,所以不要看到2002就沸腾了,这东西不一定能用。
Linux/Windows 系统上面V4地址转换为V6地址格式为:
IPV4:1.1.1.1
IPV6:::FFFF:1.1.1.1 展开 0000:0000:0000:0000:0000:FFFF:1.1.1.1
关键数据结构
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 16)]
private struct IPV62V4ADDR
{
[FieldOffset(0)]
public long R1;
[FieldOffset(8)]
public ushort R2;
[FieldOffset(10)]
public ushort R3;
[FieldOffset(12)]
public uint R4;
}
V6ToV4(V6地址转换为V4地址)
#if NETCOREAPP
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[SecurityCritical]
[SecuritySafeCritical]
public static IPEndPoint V6ToV4(IPEndPoint address)
{
if (address == null)
{
return null;
}
IPAddress host = IPFrame.V6ToV4(address.Address);
if (host == null)
{
return null;
}
return new IPEndPoint(host, address.Port);
}
#if NETCOREAPP
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[SecurityCritical]
[SecuritySafeCritical]
public static IPAddress V6ToV4(IPAddress address)
{
if (address == null)
{
return null;
}
if (address.AddressFamily == AddressFamily.InterNetwork)
{
return address;
}
byte[] buff = address.GetAddressBytes();
fixed (byte* chunk = buff)
{
IPV62V4ADDR* p = (IPV62V4ADDR*)chunk;
if (p->R1 != 0 || p->R2 != 0)
{
return null;
}
if (p->R3 != ushort.MaxValue)
{
return null;
}
return new IPAddress(p->R4);
}
}
V4ToV6(V4地址转换为V6地址)
#if NETCOREAPP
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[SecurityCritical]
[SecuritySafeCritical]
public static IPEndPoint V4ToV6(IPEndPoint address)
{
if (address == null)
{
return null;
}
IPAddress host = IPFrame.V4ToV6(address.Address);
if (host == null)
{
return null;
}
return new IPEndPoint(host, address.Port);
}
#if NETCOREAPP
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
[SecurityCritical]
[SecuritySafeCritical]
public static IPAddress V4ToV6(IPAddress address)
{
if (address == null)
{
return null;
}
if (address.AddressFamily == AddressFamily.InterNetwork)
{
byte[] buff = new byte[16];
fixed (byte* chunk = buff)
{
fixed (byte* v4 = address.GetAddressBytes())
{
IPV62V4ADDR* p = (IPV62V4ADDR*)chunk;
p->R3 = ushort.MaxValue;
p->R4 = *(uint*)v4;
}
}
return new IPAddress(buff);
}
return address;
}