C#-将指向sockaddr结构的IntPtr转换为IPAddress
从一个p/调用的本机函数中,我得到一个指向结构的。我怎样才能把它转换成一个文件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
谢谢 您必须在C#中创建相应的结构。使用以下代码(
p
就是您IntPtr
):
你可以把它“读”给C。代码的其余部分很简单,因为您将在
sau数据中拥有IP地址
,因为您不能直接封送
asockaddr
类型为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));
}
}