Почему я вижу дубликаты пакетов при использовании сокетов для получения широковещательных пакетов UDP на Windows7, но не на XP? - PullRequest
6 голосов
/ 14 декабря 2011

Позвольте мне сразу заявить, что программирование сокетов является для меня довольно новым.Кроме того, код, о котором я спрашиваю, работал в течение нескольких лет, и проблема, которую я обсуждаю, возникла только тогда, когда мы перешли с поддержки Windows XP на Windows 7.

Я работаю над приложением C #, которое отправляети получает сетевые пакеты.Это своего рода приложение типа сетевого анализатора, поэтому целостность данных очень важна.С тех пор как мы мигрировали с Windows XP на Windows 7 , когда мы UDP Broadcast (255.255.255.255) пакетов, мы получаем пакеты дважды.(т.е. я отправляю 610 пакетов, я получаю 1220 пакетов).

Я проверил с помощью WireShark, что пакеты принимаются только один раз. Кроме того, у нас есть некоторый старый код сокетов C ++, который имелбыл заменен кодом .NET.Более старый код C ++ не указывает на дубликаты.Они оба указывают на 610 отправленных пакетов, 610 полученных пакетов.

Код имеет высокую степень многопоточности и разделен между различными классами, но, собрав некоторые части вместе, код приема выглядит следующим образом:

public class RawSocket : Socket
{
    public RawSocket( IPAddress address, int receiveBufferSize, bool receiveAll )
        : base( AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP )
    {
        Bind( new IPEndPoint( address, 0 ) );

        ReceiveBufferSize = receiveBufferSize;

        ReceiveTimeout = 500; // half-a-second

        if ( receiveAll ) {
            byte[] incoming = BitConverter.GetBytes( 1 );
            byte[] outgoing = BitConverter.GetBytes( 1 );
            IOControl( IOControlCode.ReceiveAll, incoming, outgoing );
        }
    }
}

_device = new RawSocket( /* IP Address Specified Here */ );

А затем в коде, ответственном за чтение ...

byte[] buffer = new byte[ 65536 ];
int read = _device.Receive( buffer );
if (read > 0)
{
    _packet = new byte[ size ];
    _packet.BlockCopy( buffer, offset, size );
}

Итак, мой вопрос: что изменилось с API сокетов .NET между Windows XP и Windows 7, что могло бы вызвать такое поведение?Я читал темы, которые указывают, что есть различия, но ничего подобного.Трассировка кода заставляет меня думать, что это связано с поведением метода Receive() в классе Socket, которое может отличаться.Любая помощь будет оценена!

1 Ответ

5 голосов
/ 17 января 2012

Согласно спецификации это ожидаемое поведение.

http://msdn.microsoft.com/en-us/library/system.net.sockets.iocontrolcode(v=vs.110).aspx говорит, что ReceiveAll равно константе Winsock 2 SIO_RCVALL.

http://msdn.microsoft.com/en-us/library/windows/desktop/ee309610(v=vs.85).aspx говорит:

В Windows Server 2008 и более ранних версиях параметр IOCTL SIO_RCVALL будет не перехватывать локальные пакеты, отправленные из сетевого интерфейса. это включенные пакеты, полученные на другом интерфейсе и переданные сетевой интерфейс, указанный для SOC_RCVALL IOCTL.

в Windows 7 и Windows Server 2008 R2, это было изменено, чтобы локальные пакеты отправленные из сетевого интерфейса также фиксируются. Это включает пакеты, полученные на другом интерфейсе и затем перенаправленные сетевой интерфейс привязан к сокету с SIO_RCVALL IOCTL.

...