Domanda


In IPv4, La versione 3 di IGMP aggiunge supporto per "Filtro di origine", ovvero la possibilità di un sistema di segnalare l'interesse nella ricezione di pacchetti solo da indirizzi di origine specifici.

Sto usando IGMPV3 in un'applicazione C# per supportare questo comportamento. Ecco come lo faccio.

Ora sono in corso per aggiungere supporto a IPv6 nella mia applicazione e devo ottenere lo stesso comportamento di IPv4. Da quello che ho letto, il protocollo equivalente a IGMPV3 in IPv6 è Mldv2. Qualcuno ha qualche idea su come implementarlo in C# con socket?

Grazie!

È stato utile?

Soluzione

Il RFC3678 L'API indipendente del protocollo è disponibile solo in Vista+, il che potrebbe spiegare il problema.

Se il runtime c# supporta completamente IPv6 dovrai provare ad abbinare il Group_req o Group_source_req strutture. Non esiste un'API specifica IPv6 per SSM corrispondente all'API IPv4 perché gli sviluppatori hanno finalmente abbandonato l'inano duplicazione delle API e infine si sono stabiliti su un unico super set.

Purtroppo è probabile che c# implementa ipv6_mreq per AddMembership e AddSourceMembership non riesce. La documentazione è completamente assente nei dettagli.

Tutti i SocketOptionName I valori richiesti non sono definiti in C#:

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

Altri suggerimenti

Per seguire la risposta di Steve-O, è ancora possibile eseguire il filtraggio di origine in IPv6 in C# anche se System.Net.sockets.SocketOptionName Enumeration non definisce le opzioni richieste lanciando direttamente il numero.

(SocketOptionName) 45; //MCAST_JOIN_SOURCE_GROUP

Il setSocketOption della funzione del socket consentirà alla chiamata di andare al "socket windows" anche se l'opzione non è riconosciuta. La vera lotta diventa la struttura dei dati stessa che deve essere inviata accanto all'opzione. Per impostare il filtro della sorgente, la struttura dei dati deve essere come questa: group_source_req. La struttura precedente sta usando un file Sockaddr_Storage che di solito è all'interno di un'unione con Sockaddr_in e Sockaddr_in6. Per replicare questo comportamento possiamo definire le stesse strutture come questa:

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
}

Ora puoi creare un Sockaddr_in6 facendo questo:

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

I byte del Sockaddr_in6 possono ora essere estratti utilizzando la soluzione fornita qui e copiato direttamente in un Sockaddr_Storage precedentemente creato:

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

Ora che hai un Sockaddr_Storage, puoi assegnarlo a Group_Source_req ed estrarre i dati del gruppo_source_req come abbiamo fatto prima e usarlo come valore quando si imposta l'opzione.

socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName) 45, /*data extracted from group_source_req*/);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top