2011-09-08 6 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의 완전한 복제를 포기하고 마침내 하나의 수퍼 세트에 정착했기 때문에 IPv4 API와 일치하는 SSM을위한 IPv6 특정 API는 없습니다.

불행하게도 C#은 AddMembershipAddSourceMembership에 대해 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을 사용하여 동일한 작업을 수행하면 예외가 계속 throw됩니다. – Absolom

0

스티브 - 오의 대답에 후속하기 위해서는 C 번호도 시스템의 경우에서 IPv6에 소스 필터링을 수행하는 것은 여전히 ​​가능하다. Net.Sockets.SocketOptionName 열거는 숫자를 직접 형변환하여 필수 옵션을 정의하지 않습니다.

(SocketOptionName) 45; //MCAST_JOIN_SOURCE_GROUP 

소켓의 SetSocketOption 함수는 옵션을 인식하지 못하는 경우에도 호출을 "Windows 소켓"으로 이동합니다. 진정한 투쟁은 옵션과 함께 전송되어야하는 데이터 구조 자체가됩니다. 소스 필터링을 설정하려면 데이터 구조가 다음과 같아야합니다 : group_source_req. 이전 구조체는 보통 sockaddr_insockaddr_in6 인 유니온 내부에있는 sockaddr_storage을 사용합니다. 이 동작을 복제하기 위해 우리는 다음과 같은 구조체를 정의 할 수 있습니다 :

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를 만들 수 있습니다

에서 sockaddr_in6의 바이트는 이제 솔루션을 사용하여 추출 할 수
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_storage에 here 제공 및 직접 복사 : 이제

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*/); 
관련 문제