2011-09-08 21 views
0


、私はこの動作をサポートするために、C#アプリケーションでのIGMPv3を使用していますVersion 3 of IGMP adds support for "source filtering", that is, the ability for a system to report interest in receiving packets only from specific source addresses.のC#(IPv6マルチキャスト)IPv4の

でのMLDv2を使用する方法。 Here is how I do it.

私は現在、自分のアプリケーションでIPv6にサポートを追加する過程にあり、IPv4と同じ動作をする必要があります。私が読んだことから、IPv6のIGMPv3と同等のプロトコルはMLDv2です。どのようにC#でSocketを使ってこれを実装するかについて誰かが考えていますか?

ありがとうございます!

答えて

1

RFC3678プロトコルに依存しないAPIは、Vista +でのみ問題が説明されています。

C#ランタイムがIPv6を完全にサポートしている場合は、GROUP_REQまたはGROUP_SOURCE_REQ構造との一致を試みる必要があります。開発者が最終的にAPIの無駄な重複を放棄し、最終的に1つのスーパーセットに着手したため、IPv4 APIと一致するSSM用のIPv6固有のAPIはありません。

残念ながら、AddMembershipAddSourceMembershipの場合、C#がipv6_mreqを実装している可能性があります。ドキュメントは完全に詳細に欠けています。

必要なすべてのSocketOptionName値は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 
+0

ご回答ありがとうございます。特定のソースを持たないIPv6マルチキャストでは、ソケットオプションを設定するときにGROUP_REQ構造と一致するAddMembership(別のオプションはIPv6MulticastOptionを使用する)を使用できましたが、GROUP_SOURCE_REQとAddSourceMembershipで同じことを行うだけで例外が送出されます。 – Absolom

0

スティーヴォーの答えをフォローアップするために、それもシステムの場合はC#でのIPv6のソースフィルタリングを行うことも可能です。 Net.Sockets.SocketOptionName列挙では、数値を直接キャストして必要なオプションを定義していません。

(SocketOptionName) 45; //MCAST_JOIN_SOURCE_GROUP 

ソケットの関数SetSocketOptionは、コールオプションが認識されない場合でも、「Windowsソケット」に行かせます。実際の闘争は、そのオプションと共に送信される必要があるデータ構造そのものになります。 ソースフィルタを設定するには、データ構造は次のようにする必要があります。group_source_req。以前の構造体は通常sockaddr_insockaddr_in6のユニオン内にあるsockaddr_storageを使用しています。

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

SOCKADDR_IN6のバイトは今溶液を用いて抽出することができます:あなたは今、これを行うことにより、SOCKADDR_IN6を作成することができます

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 
} 

:この動作を再現するために、我々はこのように同じ構造体を定義することができますhereを提供し、以前に作成したSOCKADDR_STORAGEに直接コピー:

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_sに割り当てることができますource_reqを実行し、以前に行ったようにgroup_source_reqのデータを抽出し、オプションを設定するときにこれを値として使用します。

socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName) 45, /*data extracted from group_source_req*/); 
関連する問題