gpt4 book ai didi

c# - IPv4 映射的 IPv6 地址

转载 作者:太空宇宙 更新时间:2023-11-03 21:42:11 30 4
gpt4 key购买 nike

我正在尝试制作一个与 IP 版本无关的客户端/服务器。我一直在用 C++ 研究这个问题,并想出了一些可以使用 IN6ADDR_SETV4MAPPED 宏(正如 Microsoft 所推荐的那样)的方法。我按照代码示例 here完成这个;我转换地址的代码与示例没有什么不同,一切正常。我可以通过输入 IPv4 和 IPv6 地址从客户端连接到服务器(应用程序会相应地进行映射)。

现在我正在寻找 C# 中的解决方案来升级我制作的简单聊天服务器,但我一直无法找到有关如何使用映射地址的任何资源。我还没有找到一个函数可以提供与 IN6ADDR_SETV4MAPPED 或 .net 中的任何其他功能等效的功能。我的问题是:如何在 C# 中使用 IPv4 映射的 IPv6 地址(客户端)?

我尝试过的:

  1. 将字符串 "::ffff:" 添加到点分 IPv4 表示法中,使用此地址调用 Socket.Connect。生成的地址字符串类似于 ::ffff:127.0.0.1
  2. 前置字符串 "::ffff:"。将每个八位字节从点分格式转换为十六进制并用冒号分隔,调用 Socket.Connect。生成的地址字符串类似于 ::ffff:7f:0:0:1

到目前为止,这些方法都没有奏效。

服务器代码片段:

this.m_endPoint = new IPEndPoint(IPAddress.IPv6Any, 1337);
this.m_server.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
this.m_server.Bind(this.m_endPoint);
this.m_server.Listen(10);

客户端的代码片段:

public ClientNet(string host, short port)
{
IPAddress ip;
if(IPAddress.TryParse(host, out ip))
{
string[] octs = host.Split(new char[] { '.' });
host = "::ffff:";
for(int i = 0; i < octs.Length; ++i)
{
host += string.Format("{0:x}", int.Parse(octs[i]));
if(i + 1 != octs.Length)
{
host += ":";
}
}
}
else
{
throw new ClientCreateException("[in ClientNet.Constructor] Unable to create client; use IPv4 address");
}
Socket client = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
client.Connect(host, port);
. . . //More initialization
}

最佳答案

今天回过头来想我也许能弄明白。我做到了!答案很简单,我觉得自己像个傻瓜,因为一年都没有得到它。

关于我发布的代码的两件事:

  1. 应该使用 IPAddress.MaptoIPv6 (see MSDN link)而不是我写的那个愚蠢的、人为的循环,它更容易出错。

    一个。后来我在 .NET 4.0 中工作时意识到,我在示例中使用的便利函数在 .NET 4.5 之前不可用。我在这篇文章的底部拼凑了一个快速代码示例,以防其他人被困在早期版本的 .NET 中。

  2. 真正的解决方案:需要在调用 client.Connect 之前调用 client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0); ().

这是我今天编写的用于测试的示例应用程序的完整代码示例。我能够使用::1 和 127.0.0.1 作为地址建立连接。请注意,服务器 Socket 是为 IPv6 创建的,SocketOptionName.IPv6Only 选项在客户端和服务器 上设置为 0。

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace sixsharp
{
class Program
{
static void Main(string[] args)
{
if(args.Length <= 0) //run as server
RunServer();
else
RunClient(args);
Console.WriteLine("Press enter to close.");
Console.ReadLine();
}
static void RunServer()
{
using(Socket serv = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
{
serv.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
serv.Bind(new IPEndPoint(IPAddress.IPv6Any, 1337));
serv.Listen(5);
Console.Write("Listening for client connection...");
using(Socket client = serv.Accept())
{
Console.WriteLine("Client connection accepted from {0}", client.RemoteEndPoint.ToString());
byte[] buf = new byte[128];
client.Receive(buf, 128, SocketFlags.None);
Console.WriteLine("Got \'{0}\' from client", Encoding.ASCII.GetString(buf));
Console.WriteLine("Echoing response");
client.Send(buf);
client.Shutdown(SocketShutdown.Both);
}
}
Console.WriteLine("Done.");
}
static void RunClient(string[] args)
{
using(Socket client = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
{
client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
Console.WriteLine("Setting up address, input is {0}", args[0]);
IPEndPoint ep;
try
{
ep = new IPEndPoint(IPAddress.Parse(args[0]), 1337);
}
catch(FormatException fe)
{
Console.WriteLine("IP address was improperly formatted and not parsed.");
Console.WriteLine("Detail: {0}", fe.Message);
return;
}
if(ep.AddressFamily == AddressFamily.InterNetwork)
{
ep = new IPEndPoint(ep.Address.MapToIPv6(), ep.Port);
if(!ep.Address.IsIPv4MappedToIPv6 || ep.Address.AddressFamily != AddressFamily.InterNetworkV6)
{
Console.WriteLine("Error mapping IPv4 address to IPv6");
return;
}
}
Console.WriteLine("Connecting to server {0} ...", ep.ToString());
try
{
client.Connect(ep);
}
catch(Exception ex)
{
Console.WriteLine("Unable to connect.\n Detail: {0}", ex.Message);
return;
}
client.Send(Encoding.ASCII.GetBytes("This is a test message. Hello!"));
byte[] buf = new byte[128];
client.Receive(buf);
Console.WriteLine("Got back from server: {0}", Encoding.ASCII.GetString(buf));
client.Shutdown(SocketShutdown.Both);
}
Console.WriteLine("Done.");
}
}
}

客户端输出:

Setting up address, input is 10.2.6.179
Connecting to server [::ffff:10.2.6.179]:1337 ...
Got back from server: This is a test message. Hello!

Done.
Press enter to close.

服务器输出:

Listening for client connection...Client connection accepted from [::ffff:10.2.6.179]:56275
Got 'This is a test message. Hello!
' from client
Echoing response
Done.
Press enter to close.

提供早期 .NET 版本中缺失的便捷功能的示例扩展方法:

static class IPAddressExtensions
{
public static IPAddress MapToIPv6(this IPAddress addr)
{
if(addr.AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException("Must pass an IPv4 address to MapToIPv6");

string ipv4str = addr.ToString();

return IPAddress.Parse("::ffff:" + ipv4str);
}

public static bool IsIPv4MappedToIPv6(this IPAddress addr)
{
bool pass1 = addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6, pass2;

try
{
pass2 = (addr.ToString().StartsWith("0000:0000:0000:0000:0000:ffff:") ||
addr.ToString().StartsWith("0:0:0:0:0:ffff:") ||
addr.ToString().StartsWith("::ffff:")) &&
IPAddress.Parse(addr.ToString().Substring(addr.ToString().LastIndexOf(":") + 1)).AddressFamily == AddressFamily.InterNetwork;
}
catch
{
return false;
}

return pass1 && pass2;
}
}

关于c# - IPv4 映射的 IPv6 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18795398/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com