Чтобы проконтролировать ответ Steve-o, все еще возможно выполнить фильтрацию исходного кода в IPv6 в C #, даже если перечисление System.Net.Sockets.SocketOptionName не определяет требуемые параметры путем непосредственного приведения числа.
(SocketOptionName) 45; //MCAST_JOIN_SOURCE_GROUP
Функция SetSocketOption сокета разрешит вызову перейти к «сокету Windows», даже если опция не распознана.Настоящей борьбой становится сама структура данных, которую необходимо отправить вместе с опцией.Чтобы установить фильтрацию источника, структура данных должна быть такой: group_source_req .Предыдущая структура использует sockaddr_storage , который обычно находится внутри объединения с sockaddr_in и 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
}
Теперь вы можете создать 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_in6.используя предоставленное решение здесь и скопировав его непосредственно в ранее созданное 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_source_req и извлечь данные из group_source_req какмы делали это раньше и использовали это значение в качестве значения при установке опции.
socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName) 45, /*data extracted from group_source_req*/);