Frage


In IPv4, Version 3 von IGMP fügt Unterstützung für die "Quellfilterung" hinzu, dh die Fähigkeit, dass ein System Interesse am Empfang von Paketen meldet nur Aus bestimmten Quelladressen.

Ich verwende IGMPV3 in einer C# -Anwendung, um dieses Verhalten zu unterstützen. So mache ich es.

Ich bin jetzt dabei, IPv6 in meiner Anwendung Unterstützung hinzuzufügen, und ich muss das gleiche Verhalten wie in IPv4 erhalten. Nach dem, was ich gelesen habe, ist das äquivalente Protokoll zu IGMPv3 in IPv6 Mldv2. Hat jemand eine Idee, wie er dies in C# mit Socket implementieren kann?

Vielen Dank!

War es hilfreich?

Lösung

Das RFC3678 Protokollunabhängige API ist nur in Vista+ verfügbar, was das Problem erklären könnte.

Wenn C# Runtime IPv6 vollständig unterstützt, müssen Sie versuchen, die zu entsprechen Group_Req oder Gruppe_source_req Strukturen. Es gibt keine IPv6 -spezifische API für SSM, die mit der IPv4 -API übereinstimmt, da Entwickler schließlich die verrückte Duplikation von APIs aufgegeben und sich schließlich auf dem einen Super -Set entschieden haben.

Es ist leider wahrscheinlich, dass C# implementiert ipv6_mreq zum AddMembership und AddSourceMembership scheitert. Die Dokumentation fehlt im Detail vollständig.

All die SocketOptionName Die erforderlichen Werte sind in C#nicht definiert:

/* 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

Andere Tipps

Um die Antwort von Steve-O zu verfolgen, ist es weiterhin möglich, die Quellenfilterung in IPv6 in C# durchzuführen, auch wenn das System.net.Sockets.SocketOptionName Enumeration die erforderlichen Optionen nicht definiert, indem die Nummer direkt gegossen wird.

(SocketOptionName) 45; //MCAST_JOIN_SOURCE_GROUP

In der FunktionsetsockeToption der Socket wird der Anruf zum "Windows Socket" geleitet, auch wenn die Option nicht erkannt wird. Der eigentliche Kampf wird zur Datenstruktur selbst, die neben der Option neben der Option gesendet werden muss. Um die Quellfilterung der Datenstruktur festzulegen, muss wie folgt sein: gruppe_source_req. Die vorherige Struktur verwendet a SOCKADDR_STORAGE das ist normalerweise in einer Vereinigung mit SOCKADDR_IN und SOCKADDR_IN6. Um dieses Verhalten zu replizieren, können wir dieselben Strukturen wie diese definieren:

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
}

Sie können jetzt ein Sockaddr_in6 erstellen, indem Sie darauf folgen:

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];
}

Die Bytes des SockadDR_IN6 können jetzt mithilfe der bereitgestellten Lösung extrahiert werden hier und direkt in eine zuvor erstellte Sockaddr_Storage kopiert:

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];
}

Nachdem Sie nun über ein Sockaddr_Storage verfügen, können Sie sie gruppen_source_req zuweisen und die Daten der Gruppe der Gruppe_Source_req wie früher extrahieren und dies als Wert verwenden, wenn Sie die Option festlegen.

socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName) 45, /*data extracted from group_source_req*/);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top