我试图将一些netlink socket代码从C语言移植到C#。代码与链接中的代码相同:
首先,我们移植sockaddr_nl
结构(c source):
[StructLayout(LayoutKind.Sequential)]
public struct sockaddr_nl
{
public ushort nl_family;
public ushort nl_pad;
public uint nl_pid;
public uint nl_groups;
}
然后,使用
获取套接字fdvar fd = -1;
fd = UnixFiller.socket(
(int) UnixAddressFamily.AF_NETLINK,
(int) UnixSocketType.SOCK_RAW | 0x80000,
0 /* NETLINK_ROUTE */
);
if(fd < 0)
FatalError("Failed to create routing socket.");
UnixFiller.socket
只是来自libc的DLLImport。此调用按预期成功。
然而,下一步是将富有表现力的sockaddr_nl
结构转换为bind所消耗的族+字节数组结构sockaddr
:
bind(fd, (struct sockaddr*)&address, sizeof(address));
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
据我所知,在C#中会出现这种情况:
[StructLayout(LayoutKind.Sequential)]
public struct sockaddr
{
public ushort sa_familiy;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] byte[] sa_data;
}
问题
首先,bind
导入应该如何?
[DllImport("libc", SetLastError = true, EntryPoint = "bind")]
public static extern int bind(int sockfd, ??? addr, int addrlen);
??? =未知。
接下来,如何将演员从sockaddr_nl
移植到sockaddr
,以便将正确的格式传递给bind
?
答案 0 :(得分:0)
您无法在sockaddr_nl
和sockaddr
之间 ,因为您有一个将会阻碍的引用(sa_data
)。如果它是fixed
缓冲区(即直接在结构中的原始数据),那么它可能会很好,但然后你需要始终使用unsafe
。但是,我不清楚它会是什么样子;看起来你的意思是sa_data
的14个字节是sockaddr_nl
的内容? (我只计算12个字节,请注意)
要在byte[]
上编写结构,您可以使用unsafe
代码:
static unsafe void Main()
{
var val = new sockaddr_nl
{
nl_family = 1, nl_pad = 2, nl_pid = 3, nl_groups = 4
};
byte[] data = new byte[14];
Console.WriteLine("size of struct: " + sizeof(sockaddr_nl));
// show value before
Console.WriteLine(BitConverter.ToString(data));
// thunk over the data
fixed (byte* p = data)
{
*((sockaddr_nl*)p) = val;
}
// show value after
Console.WriteLine(BitConverter.ToString(data));
}
这有输出:
size of struct: 12
00-00-00-00-00-00-00-00-00-00-00-00-00-00
01-00-02-00-03-00-00-00-04-00-00-00-00-00