首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C# (IPv6组播)中使用MLDv2

如何在C# (IPv6组播)中使用MLDv2
EN

Stack Overflow用户
提问于 2011-09-09 03:32:04
回答 2查看 965关注 0票数 0

在IPv4中,版本3增加了对“源过滤”的支持,即系统报告只从特定源地址接收数据包的兴趣的能力。

我在一个C#应用程序中使用IGMPv3来支持这种行为。Here is how I do it.

我现在正在向我的应用程序中添加对IPv6的支持,并且我需要获得与IPv4中相同的行为。据我所知,IPv6中与IGMPv3等效的协议是MLDv2。有没有人知道如何在C#中使用Socket实现这一点?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-09-09 15:02:49

只有在Vista+中才能使用与RFC3678协议无关的应用程序接口,这可能可以解释这个问题。

如果C#运行时确实完全支持IPv6,则必须尝试匹配GROUP_REQGROUP_SOURCE_REQ结构。没有与SSM匹配的特定于IPv6的IPv4,因为开发人员最终放弃了空洞的API复制,最终选择了一个超集。

不幸的是,C#很可能为AddMembership实现了ipv6_mreq,而AddSourceMembership失败了。文档中完全没有详细信息。

C#中未定义所需的所有SocketOptionName值:

代码语言:javascript
复制
/* RFC 3678 */
#define MCAST_JOIN_GROUP       41
#define MCAST_LEAVE_GROUP      42
#define MCAST_BLOCK_SOURCE     43
#define MCAST_UNBLOCK_SOURCE   44
#define MCAST_JOIN_SOURCE_GROUP        45
#define MCAST_LEAVE_SOURCE_GROUP       46
#define MCAST_MSFILTER         47
票数 1
EN

Stack Overflow用户

发布于 2017-11-23 02:36:31

为了跟进Steve-o的回答,仍然可以在C#的IPv6中进行源过滤,即使System.Net.Sockets.SocketOptionName枚举没有通过直接转换数字来定义所需的选项。

代码语言:javascript
复制
(SocketOptionName) 45; //MCAST_JOIN_SOURCE_GROUP

套接字的函数SetSocketOption将让调用转到"windows套接字“,即使该选项未被识别。真正的难题变成了数据结构本身,它需要与选项一起发送。要设置源过滤,数据结构必须如下所示:group_source_req。前面的结构使用了一个sockaddr_storage,它通常在与sockaddr_insockaddr_in6的联合中。为了复制这种行为,我们可以像这样定义相同的结构:

代码语言:javascript
复制
private unsafe struct sockaddr_storage
{
    public short ss_family;             //2
    private fixed byte __ss_pad1[6];    //6
    private Int64 __ss_align;           //8
    private fixed byte __ss_pad2[112];  //112
}
private unsafe struct sockaddr_in
{
    public ushort sin_family;       //2
    public ushort sin_port;         //2
    public fixed byte sin_addr[4];  //4
    private fixed byte sub_zero[8]; //8
 }
private unsafe struct sockaddr_in6
{
    public ushort sin6_family;       //2
    public ushort sin6_port;         //2
    public int sin6_flowinfo;        //4
    public fixed byte sin6_addr[16]; //16
    public uint sin6_scope_id;       //4
}
private struct group_source_req
{
    public uint gr_interface;           //4
    //Compiler add a padding here:      //4
    public sockaddr_storage gr_group;   //128
    public sockaddr_storage gr_source;  //128
}

现在,您可以通过执行以下操作来创建sockaddr_in6:

代码语言:javascript
复制
sockaddr_in6 sockIn = new sockaddr_in6
{
    sin6_family = (ushort) endPoint.AddressFamily,
    sin6_port = (ushort)endPoint.Port,
    sin6_scope_id = 0
};
for (int i = 0; i < endPoint.Address.GetAddressBytes().Length; i++)
{
    sockIn.sin6_addr[i] = endPoint.Address.GetAddressBytes()[i];
}

现在可以使用提供的解决方案here提取sockaddr_in6的字节,并将其直接复制到之前创建的sockaddr_storage中:

代码语言:javascript
复制
sockaddr_storage sock = new sockaddr_storage
{
    ss_family = (short)endPoint.AddressFamily
};
//[...]
byte[] sockInData = getBytes(sockIn);
byte* sockData = (byte*) &sock;
for (int i = 0; i < sockInData.Length; i++)
{
    sockData [i] = sockInData[i];
}

现在您有了一个sockaddr_storage,您可以将其分配给group_source_req并提取group_source_req的数据,就像我们前面所做的那样,并在设置该选项时将其用作值。

代码语言:javascript
复制
socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName) 45, /*data extracted from group_source_req*/);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7353437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档