Мониторинг ресурсов сети

199
18 января 2018, 17:50

Нужно сделать программу которая показывает: на сколько каждый процесс использует сеть и на какой ИП он отправляет данные. Так сказать аналог "Монитора Ресурсов" в Windows. С помощью чего это можно реализовать? Если есть какой-то пример буду признателен.

(Желательно C#)

Answer 1

Вот как вариант получение с помощью cmd.exe списка открытых портов и повесить делать снимки библиотеку SharpPcap.

Пример полного кода:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Text.RegularExpressions;
using SharpPcap;
namespace ConsoleApp3
{
    /// <summary>
    /// Информация о процессе
    /// </summary>
    public class ProcessPerformanceInfo
    {
        public int ProcessID { get; set; }
        public long NetSendBytes { get; set; }
        public long NetRecvBytes { get; set; }
        public long NetTotalBytes { get; set; }
    }

    public class Program
    {
        /// <summary>
        /// Информация о процессе
        /// </summary>
        private static ProcessPerformanceInfo _processPerformanceInfo;
        /// <summary>
        /// Последнее время обновления
        /// </summary>
        private static DateTime _lastUpdateDateTime = DateTime.Now;

        /// <summary>
        /// Главный метод приложения
        /// </summary>
        public static void Main(string[] args)
        {
            //Получаем идентификатор процеса
            var processId = ReadIntValue("Введите ID процеса: ");
            _processPerformanceInfo = new ProcessPerformanceInfo()
            {
                ProcessID = processId
            };
            Console.WriteLine();
            //С помощью CMD получаем список всех открытых портов и выводим на экран
            var ports = GetPorts();
            //Выводим список открытых портов
            Console.Write("Список открытых портов: ");
            foreach (var port in ports)
            {
                Console.Write(port + ",");
            }
            Console.WriteLine();
            //Получаем ip для снифинга
            Console.WriteLine();
            var ip = GetIpForCapture();
            Console.WriteLine();
            //Получаем список сетевых карт и выводим на экран чтоб выбрать какую будем снифить
            var devices = CaptureDeviceList.Instance;
            //Проверяем что на машине есть хоть одна
            int devicesCount = devices.Count;
            if (devicesCount < 1)
            {
                Console.WriteLine("Не обнаруженно не одной сетевой карты");
                Console.ReadKey();
                return;
            }
            //Получение номера сетевой карты
            var cardNumber = GetCardNumber(devices, devicesCount);
            Console.WriteLine();
            //Проходим по каждому порту и ставим хук на примем и отправку для указанной карты
            foreach (var port in ports)
            {
                CaptureFlowReceive(ip, port, cardNumber);
                CaptureFlowSend(ip, port, cardNumber);
            }
            //В бесконечном цикле читаем консоль чтоб она не закрылась
            while (true)
            {
                Console.ReadKey();
            }
        }
        /// <summary>
        /// Получение номера сетевой карты
        /// </summary>
        private static int GetCardNumber(CaptureDeviceList devices, int devicesCount)
        {
            //Показываем пользователю список карт и просим выбрать одну по номеру
            Console.WriteLine("Список сетевых карт: ");
            for (int i = 0; i < devices.Count; i++)
            {
                Console.WriteLine($" [{i}]\t-\t{devices[i].Description}");
            }
            //Ждем пока пользователь не выберет ту которую хочет использовать
            int cardNumber;
            do
            {
                cardNumber = ReadIntValue("Введите номер сетевой карты: ");
            }
            while (cardNumber < 0 || cardNumber >= devicesCount);
            return cardNumber;
        }
        /// <summary>
        /// Получить ip для снифинга
        /// </summary>
        private static string GetIpForCapture()
        {
            //Получаем список IP
            var addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
            //Показываем пользователю список IP
            Console.WriteLine("Список IP для снифинга: ");
            for (int i = 0; i < addressList.Length; i++)
            {
                Console.WriteLine($" [{i}]\t-\t{addressList[i]}");
            }
            //Ждем пока пользователь выберет адрес для прослушки
            int ipNumber;
            do
            {
                ipNumber = ReadIntValue("Введите номер IP для снифинга:");
            }
            while (ipNumber < 0 || ipNumber >= addressList.Length);
            return addressList[ipNumber].ToString();
        }
        /// <summary>
        /// Метод рекурсивно вызывает чтение в консоли пока пользователь не введет число
        /// </summary>
        private static int ReadIntValue(string text)
        {
            bool inputResult;
            int processId;
            do
            {
                Console.Write(text);
                var input = Console.ReadLine();
                inputResult = int.TryParse(input, out processId);
            }
            while (!inputResult);
            return processId;
        }
        /// <summary>
        /// Получение списка всех открытых протов (С помощью CMD получаем список все открытых портов)
        /// </summary>
        private static List<int> GetPorts()
        {
            //Вызываем команду netstat -ano для получения списка всех открытых портов
            var cmdProcess = new Process
            {
                StartInfo =
                {
                    FileName = "cmd.exe",
                    UseShellExecute = false,
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                }
            };
            cmdProcess.Start();
            cmdProcess.StandardInput.WriteLine("netstat -ano");
            cmdProcess.StandardInput.WriteLine("exit");
            //После чего пройдемся по всем строкам что вывела cmd и добавим порты в коллекцию
            var ports = new List<int>();
            var reg = new Regex("\\s+", RegexOptions.Compiled);
            string line;
            while ((line = cmdProcess.StandardOutput.ReadLine()) != null)
            {
                line = line.Trim();
                if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
                {
                    line = reg.Replace(line, ",");
                    string[] arr = line.Split(',');
                    if (arr[4] == _processPerformanceInfo.ProcessID.ToString())
                    {
                        string soc = arr[1];
                        int pos = soc.LastIndexOf(':');
                        int pot = int.Parse(soc.Substring(pos + 1));
                        ports.Add(pot);
                    }
                }
                else if (line.StartsWith("UDP", StringComparison.OrdinalIgnoreCase))
                {
                    line = reg.Replace(line, ",");
                    string[] arr = line.Split(',');
                    if (arr[3] == _processPerformanceInfo.ProcessID.ToString())
                    {
                        string soc = arr[1];
                        int pos = soc.LastIndexOf(':');
                        int pot = int.Parse(soc.Substring(pos + 1));
                        ports.Add(pot);
                    }
                }
            }
            cmdProcess.Close();
            return ports;
        }
        /// <summary>
        /// Установка хука на отправку
        /// </summary>
        private static void CaptureFlowSend(string ip, int portID, int deviceID)
        {
            //Запрашиваем сетевую карту
            ICaptureDevice device = CaptureDeviceList.New()[deviceID];
            //Ставим событе которое будет вызываться при отправке пакета
            device.OnPacketArrival += OnPacketArrivalSend;
            //Открываем карту для снятия данных
            int readTimeoutMilliseconds = 1000;
            device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
            //Формируем фильтр для снифинга пакетов
            string filter = "src host " + ip + " and src port " + portID;
            device.Filter = filter;
            //Стартуем снифинг
            device.StartCapture();
        }
        private static void CaptureFlowReceive(string IP, int portID, int deviceID)
        {
            //Запрашиваем сетевую карту
            ICaptureDevice device = CaptureDeviceList.New()[deviceID];
            //Ставим событе которое будет вызываться при получение пакета
            device.OnPacketArrival += OnPacketArrivalReceive;
            //Открываем карту для снятия данных (И устанавливаем таймаут считывания)
            int readTimeoutMilliseconds = 1000;
            device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
            //Формируем фильтр для снифинга пакетов
            string filter = "dst host " + IP + " and dst port " + portID;
            device.Filter = filter;
            //Стартуем снифинг
            device.StartCapture();
        }
        /// <summary>
        /// Обработка отправки пакета
        /// </summary>
        private static void OnPacketArrivalSend(object sender, CaptureEventArgs e)
        {
            var dataLength = e.Packet.Data.Length;
            _processPerformanceInfo.NetSendBytes += dataLength;
            //Вызываем обновление
            RefershInfo();
        }
        //Обработка получения пакета
        private static void OnPacketArrivalReceive(object sender, CaptureEventArgs e)
        {
            var dataLength = e.Packet.Data.Length;
            _processPerformanceInfo.NetRecvBytes += dataLength;
            //Вызываем обнволение
            RefershInfo();
        }
        //Обновление информации
        public static void RefershInfo()
        {
            //Проверяем что если с последнего обновления прошла секунда, то выводим результат, иначе ждем дальше
            if (DateTime.Now > _lastUpdateDateTime + TimeSpan.FromSeconds(1))
            {
                _lastUpdateDateTime = DateTime.Now;
            }
            else
            {
                return;
            }
            //Получаем общее количество байт
            _processPerformanceInfo.NetTotalBytes = _processPerformanceInfo.NetRecvBytes + _processPerformanceInfo.NetSendBytes;
            //Вывод на экран
            Console.WriteLine();
            Console.WriteLine(DateTime.Now.ToLongDateString());
            Console.WriteLine("proc NetTotalBytes : " + _processPerformanceInfo.NetTotalBytes);
            Console.WriteLine("proc NetSendBytes : " + _processPerformanceInfo.NetSendBytes);
            Console.WriteLine("proc NetRecvBytes : " + _processPerformanceInfo.NetRecvBytes);
            //Обнуление счетчиков
            _processPerformanceInfo.NetRecvBytes = 0;
            _processPerformanceInfo.NetSendBytes = 0;
            _processPerformanceInfo.NetTotalBytes = 0;
        }
    }
}

Пример работы (снял снимок с телеграма):

P.S. Результат будет выводиться только если у приложения реально есть сетевая активностью.

READ ALSO
Поиск по DataGrid из внутренних TextBox/ComboBox. Mvvm - C# WPF/.NET 4.x

Поиск по DataGrid из внутренних TextBox/ComboBox. Mvvm - C# WPF/.NET 4.x

Доброго дня всем! Очень интересует как поместить внутрь DataGrid несколько TextBox'ов или ComboBox'ов, что бы по ним совершать поиск по строкам или запрос...

217
При выходе с приложения не сохраняются данные в PlayerPrefs Unity Android

При выходе с приложения не сохраняются данные в PlayerPrefs Unity Android

Создал приложение в Unity на iOS всё работает, поменял платформу на Android, так всё сразу упало, я сохранял данные при выходе,

304
Подключение к базе данных firebird на C# WPF

Подключение к базе данных firebird на C# WPF

Подскажите, как можно подключиться к бд firebird на C#

268
Внедрения зависимостей

Внедрения зависимостей

Подскажите пожалуйста, как мне организовать внедрения зависимостей в 3-ох уровневой приложения с DAL, BLL i WEB в ASPNET MVC?

263