连续不安全结构之间的转换

时间:2017-06-05 13:15:14

标签: c# linux sockets netlink

我试图将一些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;
}

然后,使用

获取套接字fd
var 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));

sockaddr is

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

1 个答案:

答案 0 :(得分:0)

您无法在sockaddr_nlsockaddr之间 ,因为您有一个将会阻碍的引用(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