Теперь, когда мы знаем как получить перечень адаптеров, давайте «захватим» несколько пакетов. В этом разделе мы напишем программу, которая инициализирует сетевой адаптер и выводит информацию о каждом пакете, переходящим через него.
Функция открывающая сетевой адаптер Open(). Она перегружена и имеет следующие аргументы:
- Open()
- Open(DeviceMode mode)
- Open(DeviceMode mode, int read_timeout)
Последние два аргумента заслуживают детального рассмотрения.
DeviceMode в обычном режиме (DeviceMode.Normal), сетевой адаптер захватывает только те пакеты, которые адресованы непосредственно ему; обмен пакетами других хостов в сети игнорируется. Когда адаптер находится в беспорядочном режиме (DeviceMode.Promiscuous), он захватывает все пакеты, хотят они этого или нет. Это означает, что Libpcap / WinPcap сможет захватить пакеты адресованные другим хостам. Promiscuous(неразборчивый) режим используется по умолчанию для большинства приложений, так что мы также включим его в следующем примере. ПРИМЕЧАНИЕ: Использование этого режима в сети можно обнаружить, так что если Вы будете захватывать в Promiscuous (беспорядочном) режиме, то Ваши действия могут быть обнаружены. Используйте поиск в Интернете по ключевым словам «detect Promiscuous» для получения дополнительной информации.
read_timeout: Задает таймаут в миллисекундах. Чтения с адаптера (например, с помощью функции GetNextPacket ()) всегда будет возвращаться после read_timeout миллисекунд, даже если пакеты уже доступны. read_timeout также определяет интервал между статистическими отчетами, если адаптер в работает статистическом режиме (в режиме сбора статистики).
В следующем примере показано использование события OnPacketArrival для приема пакетов. Мы создаем обработчик событий, который вызывается всякий раз, когда новый пакет проходит через ICaptureDevice:
// Получаем устройство из списка устройств ICaptureDevice device = devices[i]; // Регистрируем событие для приёмки пакетов device.OnPacketArrival += new SharpPcap.PacketArrivalEventHandler(device_OnPacketArrival); // Открываем адаптер для получения пакетов int readTimeoutMilliseconds = 1000; device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds); Console.WriteLine("-- Listening on {0}, hit 'Enter' to stop...", device.Description); // Начинаем сбор пакетов device.StartCapture(); // Ждем нажатия Enter Console.ReadLine(); // Прекращаем процесс сбора пакетов device.StopCapture(); //Закрываем pcap устройство device.Close();
Ниже представлена реализация обработчика OnPacketArrival:
// <summary> /// Выводим время и длину полученных пакетов /// </summary> private static void device_OnPacketArrival(object sender, CaptureEventArgs packet) { DateTime time = packet.Timeval.Date; int len = packet.Data.Length; Console.WriteLine("{0}:{1}:{2},{3} Len={4}", time.Hour, time.Minute, time.Second, time.Millisecond, len); }
После того, адаптер открыт, захват может быть запущен с помощью StartCapture() или Capture(INT packetCount) функции. Эти две функции схожи, разница в том, что StartCapture() не блокирует основной поток программы, а запускается в новом потоке, в то время Capture(INT packetCount) блокирует основной поток, до тех пор пока packetCount пакеты не будут получены. При использовании StartCapture() мы должны вызвать StopCapture(), чтобы завершить процесс захвата. Для бесконечного(постоянного) захвата необходимо вызывать метод Capture().
Обе эти функции требуют, чтобы обработчик события для обработки пакетов был зарегистрирован(инициализирован) до их вызова. Этот обработчик событий вызывается устройством ICaptureDevice для каждого нового пакета, проходящего через сеть. Он получает отправителя объекта, который вызывает этот обработчик (т.е. ICaptureDevice объекта) и фактически полученного пакета, включая все заголовки протокола. Обратите внимание, что CRC обычно не присутствует в пакете, поскольку он удаляется сетевым адаптером после процедуры проверки пакета(целостности). Стоит также отметить, что большинство адаптеров отбрасывает пакеты с неправильной контрольной суммой CRC, в следствии чего так WinPcap (и, следовательно SharpPcap), как правило, не в состоянии захватить их.
Класс Packet представляет собой основной класс для захваченных пакетов. Каждый захваченный пакет имеет PcapHeader свойство, содержащее некоторую информацию (например: метка времени захвата и длины пакета). Приведенный выше пример извлекает метку и длину от каждого пакета и выводит их на экран.
Обратите внимание, что код обработчика вызывается ICaptureDevice, поэтому пользовательское приложение не имеет прямого (доступа)контроля над ним. Другой подход заключается в использовании функции GetNextPacket(), которая представлена в следующем разделе.
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds)
не получается. системе не удается обнаружить данное устройство. в чем может быть проблема?
хотя при этом при печати списка устройств он устройство находит
А если попробовать открыть в DeviceMode.Normal?
Может Ваше устройство не поддерживает этот режим.. маловероятно но всё же
Подскажите пожалуйста выдает ошибку на эти строчки:
DateTime time = packet.Timeval.Date;
int len = packet.Data.Length;
Ошибка 1 «SharpPcap.CaptureEventArgs» не содержит определения для «Timeval» и не был найден метод расширения «Timeval», принимающий тип «SharpPcap.CaptureEventArgs» в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку) и Ошибка 2 «SharpPcap.CaptureEventArgs» не содержит определения для «Data» и не был найден метод расширения «Data», принимающий тип «SharpPcap.CaptureEventArgs» в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку).
ПОЧЕМУ ТАК??
Примеры сделаны уже для устаревшей версии SharpCap, в новой немного поменяли код. 8(