C#-将指向sockaddr结构的IntPtr转换为IPAddress

C#-将指向sockaddr结构的IntPtr转换为IPAddress,c#,type-conversion,pinvoke,ip-address,intptr,C#,Type Conversion,Pinvoke,Ip Address,Intptr,从一个p/调用的本机函数中,我得到一个指向结构的。我怎样才能把它转换成一个文件 谢谢 您必须在C#中创建相应的结构。使用以下代码(p就是您IntPtr): 你可以把它“读”给C。代码的其余部分很简单,因为您将在sau数据中拥有IP地址,因为您不能直接封送asockaddr类型为IPAddress类型,所以必须首先将其封送到: [StructLayout(LayoutKind.Sequential)] internal struct sockaddr_in { internal EnumL

从一个p/调用的本机函数中,我得到一个指向结构的。我怎样才能把它转换成一个文件


谢谢

您必须在C#中创建相应的结构。使用以下代码(
p
就是您
IntPtr
):


你可以把它“读”给C。代码的其余部分很简单,因为您将在
sau数据中拥有IP地址

,因为您不能直接
封送
a
sockaddr
类型为
IPAddress
类型,所以必须首先将其封送到:

[StructLayout(LayoutKind.Sequential)]
internal struct sockaddr_in
{
    internal EnumLib.ADDRESS_FAMILIES sin_family;
    internal ushort sin_port;
    internal in_addr sin_addr;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] internal byte[] sin_zero;

    internal static sockaddr_in FromString(string host, int port)
    {
    var sockaddr = new sockaddr_in();
    var lpAddressLength = Marshal.SizeOf(sockaddr);
    WSAStringToAddress(host + ":" + port, EnumLib.ADDRESS_FAMILIES.AF_INET, IntPtr.Zero,
                      ref sockaddr, ref lpAddressLength);
    return sockaddr;
    }
}
然后可以使用
Marshal.PtrToStructure
IntPtr
中获取
sockaddr\u in
类型,如下所示:

(sockaddr_in)Marshal.ptr结构(地址、类型(sockaddr_in))

之后,从刚检索到的数据创建一个新的
IPAddress
对象应该相当简单

您可以在上面的示例中找到
EnumLib
中包含的
ADDRESS\u族
enum:


pinvoke.net上原本有更多的结构成员,如果您对它们感兴趣,但我认为在这种特定情况下您根本不需要它们。

根据@aevitas的回答,我提出了以下解决方案:

public enum SockAddrFamily
{
  Inet = 2,
  Inet6 = 23
}

[StructLayout(LayoutKind.Sequential)]
public struct SockAddr
{
  public ushort Family;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)]
  public byte[] Data;
};

[StructLayout(LayoutKind.Sequential)]
public struct SockAddrIn 
{
  public ushort Family;
  public ushort Port;
  public uint Addr;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  public byte[] Zero;
}

[StructLayout(LayoutKind.Sequential)]
public struct SockAddrIn6 
{
  public ushort Family;
  public ushort Port;
  public uint FlowInfo;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
  public byte[] Addr;
  public uint ScopeId;
};

public IPAddress ConvertSockAddrPtrToIPAddress(IntPtr sockAddrPtr)
{
  SockAddr sockAddr = (SockAddr)Marshal.PtrToStructure(sockAddrPtr, typeof(SockAddr));
  switch ((SockAddrFamily)sockAddr.Family)
  {
    case SockAddrFamily.Inet:
    {
      SockAddrIn sockAddrIn = (SockAddrIn)Marshal.PtrToStructure(sockAddrPtr, typeof(SockAddrIn));
      return new IPAddress(sockAddrIn.Addr);
    }
    case SockAddrFamily.Inet6:
    {
      SockAddrIn6 sockAddrIn6 = (SockAddrIn6)Marshal.PtrToStructure(sockAddrPtr, typeof(SockAddrIn6));
      return new IPAddress(sockAddrIn6.Addr);
    }
    default:
      throw new Exception(string.Format("Non-IP address family: {0}", sockAddr.Family));
  }
}

我用IPv4和IPv6地址成功地测试了它。

可能与@spender重复首先,IPAddress不是一个结构。其次,sockaddr可能包含IPv4或IPv6地址,所以转换并不像您提到的问题那个样简单。所以这绝对不是它的复制品。对不起,这不是我问题的答案。IPAddress不是结构,sockaddr可能包含IPv4或IPv6地址,因此转换并不像您建议的那么简单。项目中的什么定义了它是哪种结构?IntPtr是指向内存的指针,但您必须知道要读取的内存大小。指向sockaddr定义的链接:您必须检查您拥有的系统。在本例中,您可以找到使用了哪个pragma(\u WIN32\u WINNT)。有帮助的链接,请你整理一下你的答案好吗?例如,没有EnumLib的定义,也不需要调用WSAAddressToString来进行转换。我很乐意接受你的回答,如果它包含了将IntPtr转换为IPAddress所需的代码,无论是IPv4还是IPv6。谢谢你的帮助@kol为了简洁起见编辑了我的答案,并从结构中删除了两个多余的属性。如果你想完整地查看,我还添加了一个链接到pinvoke上的原始代码片段。您可能还想查看\u addr
中的
成员,特别是IPv4和IPv6互操作性。感谢您的帮助,我添加了“最终”转换器代码作为单独的答案。
public enum SockAddrFamily
{
  Inet = 2,
  Inet6 = 23
}

[StructLayout(LayoutKind.Sequential)]
public struct SockAddr
{
  public ushort Family;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)]
  public byte[] Data;
};

[StructLayout(LayoutKind.Sequential)]
public struct SockAddrIn 
{
  public ushort Family;
  public ushort Port;
  public uint Addr;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  public byte[] Zero;
}

[StructLayout(LayoutKind.Sequential)]
public struct SockAddrIn6 
{
  public ushort Family;
  public ushort Port;
  public uint FlowInfo;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
  public byte[] Addr;
  public uint ScopeId;
};

public IPAddress ConvertSockAddrPtrToIPAddress(IntPtr sockAddrPtr)
{
  SockAddr sockAddr = (SockAddr)Marshal.PtrToStructure(sockAddrPtr, typeof(SockAddr));
  switch ((SockAddrFamily)sockAddr.Family)
  {
    case SockAddrFamily.Inet:
    {
      SockAddrIn sockAddrIn = (SockAddrIn)Marshal.PtrToStructure(sockAddrPtr, typeof(SockAddrIn));
      return new IPAddress(sockAddrIn.Addr);
    }
    case SockAddrFamily.Inet6:
    {
      SockAddrIn6 sockAddrIn6 = (SockAddrIn6)Marshal.PtrToStructure(sockAddrPtr, typeof(SockAddrIn6));
      return new IPAddress(sockAddrIn6.Addr);
    }
    default:
      throw new Exception(string.Format("Non-IP address family: {0}", sockAddr.Family));
  }
}