回答
IP地址既然你不能直接Marshal
一個sockaddr
類型爲IPAddress
類型,你就必須做出a managed struct out of it率先將其編組到:
[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
獲得sockaddr_in
類型從IntPtr
像這樣:
(sockaddr_in) Marshal.PtrToStructure(address, typeof(sockaddr_in));
之後,根據您剛纔檢索的數據創建新的IPAddress
對象應該相當簡單。
您可以找到包含在EnumLib
在上面的例子在這裏ADDRESS_FAMILIES
枚舉:http://pastie.org/8103489
有該結構在最初更多的成員在pinvoke.net,只是take a look here如果你有興趣在他們,但我估計在這種特定情況下你根本不需要它們。
你能否清理一下你的答案?例如,沒有EnumLib的定義,並且不需要調用WSAAddressToString來進行轉換。如果它包含將IntPtr轉換爲IPAddress所需的代碼,那麼對於IPv4和IPv6情況,我都會很樂意接受您的答案。感謝您的幫助! – kol
@kol編輯我的答案爲簡潔並從結構中刪除了兩個多餘的屬性。如果你想完全查看它們,我還在pinvoke上添加了一個原始代碼片段的鏈接。您可能還想在'in_addr'成員上查找http://msdn.microsoft.com/en-us/library/windows/desktop/ms738571(v=vs.85).aspx,專門用於IPv4和IPv6互操作性。 – aevitas
感謝您的幫助,我添加了「最終」轉換器代碼作爲一個單獨的答案。 – kol
您必須在C#中創建相應的結構。在使用下面的代碼(p
是你IntPtr
):
(MyStruct)System.Runtime.InteropServices.Marshal.PtrToStructure(p, typeof(MyStruct));
可以 「讀」 它的C#。代碼休息是很容易的,因爲你將不得不在sa_data
繼@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地址進行了測試。
- 1. 類型轉換sockaddr結構
- 2. 如何將一個指向c結構的指針轉換爲jna結構
- 3. 將NSData轉換爲swift中的sockaddr結構體
- 4. 轉換ID轉換爲sockaddr在Objective-C
- 5. 轉換陣列結構到IntPtr的
- 6. 將HWND轉換爲IntPtr(CLI)
- 7. 轉換一個結構到一個IntPtr
- 8. 如何將sockaddr結構轉換爲sockaddr_in - C++網絡套接字ubuntu UDP
- 9. IntPtr轉換爲字節[] c#
- 10. 在C#中將IntPtr轉換爲int *?
- 11. 如何將位圖轉換爲intptr C#
- 12. 將IntPtr轉換爲CWPSTRUCT
- 13. 將筆轉換爲IntPtr
- 14. 將指向結構成員變量的(常規)指針轉換爲指向整個結構的指針
- 15. 轉換結構爲char指針在C#
- 16. 無法將:: C *轉換爲C *的指針結構
- 17. 指向本地結構的指針如何轉換爲webassembly?
- 18. 將MMTPMsg結構從C++轉換爲c#
- 19. 將C結構轉換爲C++類
- 20. C到C++:將結構轉換爲類
- 21. 將C++結構轉換爲C#
- 22. 將結構從C轉換爲C++(POD)
- 23. 將C函數指針結構轉換爲C#
- 24. 將c中的結構轉換爲pywin32?
- 25. 在構建時將C++結構轉換爲C#結構
- 26. 如何將結構轉換爲D中的C指針?
- 27. 轉換C++指針結構,以C#
- 28. C將樹結構轉換爲JSON
- 29. 將C結構轉換爲Java
- 30. 將C結構轉換爲delphi
[p/invoke C函數返回指向結構體的指針]的可能的重複(http://stackoverflow.com/questions/779444/p-invoke-c-function-that-returns-pointer-toa-a- struct) – spender
@spender首先,IPAddress不是一個結構。其次,sockaddr可能包含IPv4或IPv6地址,因此轉換並不像您提到的問題那樣簡單。所以這絕對不是它的重複。 – kol