Пинг нескольких адресов одновременно

86
12 марта 2022, 00:20

Всем здравствуйте! Не судите строго, т.к. только начинаю в этом разбираться. Задача у меня следующая: имеется список ip-адресов в excel файле и их необходимо проверять на доступность. В принципе, то что у меня сейчас есть устраивает, но не совсем, т.к. если список очень большой, то уходит достаточно много времени на проверку доступности этих ip-адресов, потому что проверка идет последовательно, т.е. сначала один ip-проверили, потом второй, третий и т.д. Можно ли этот процесс как-то ускорить, допустим запустить несколько параллельных процессов на проверку доступности ip-адресов? Посмотрев Интернет (в том числе и здесь), я так понимаю, что можно использовать асинхронный метод, но я что-то делаю не так, поэтому у меня особо ничего не получается... Помогите, пожалуйста :)

private static async void Run()
    {
            string path;
            Console.Write("Введите путь, указав имя файла: ");
            path = Convert.ToString(Console.ReadLine());
            int i;
            int j = 1;
            int N;
            Console.Write("Количество строк: ");
            N = Convert.ToInt32((Console.ReadLine()));

            StreamReader f = new StreamReader(path);
            Excel.Application ObjWorkExcel = new Excel.Application();
            Excel.Workbook ObjWorkBook = ObjWorkExcel.Workbooks.Open(@"" + path + "", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            Excel.Worksheet ObjWorkSheet = (Excel.Worksheet)ObjWorkBook.Sheets[1];
        for (j = 1; j <= 2; j++)
            {
                for (i = 1; i <= N; i++)
                {
                    string pinger = ObjWorkSheet.Cells[i, j].Text;
                    if (ObjWorkSheet.Rows[i].Text == null)
                    {
                        i++;
                    }
                    Ping pingSender = new Ping();
                    string data = "aaaaaaa";
                    byte[] buffer = Encoding.ASCII.GetBytes(data);
                    PingOptions options = new PingOptions(64, true);
                    try
                    {
                        PingReply reply = await pingSender.SendPingAsync(pinger);
                        if (reply.Status == IPStatus.Success)
                        {
                            Console.WriteLine(string.Format("{0} {1}", reply.Address, reply.Status));
                            (ObjWorkSheet.Cells[i, j] as Excel.Range).Interior.ColorIndex = 4;
                        }
                        else
                        {
                            Console.WriteLine(string.Format("{0}  {1}", reply.Address, reply.Status));
                            (ObjWorkSheet.Cells[i, j] as Excel.Range).Interior.ColorIndex = 3;
                        }
                    }
                    catch (Exception)
                    {
                        (ObjWorkSheet.Cells[i, j] as Excel.Range).Interior.ColorIndex = 6;
                    }
                }
        }
        Console.WriteLine("ЗАВЕРШЕНО");
        Console.ReadLine();
        ObjWorkExcel.Quit();
    }
Answer 1

Пинг на чистом async/await:

using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.Concurrent;
namespace TestPing
{
    class Program
    {
        class PingResult
        {
            public IPAddress Ip { get; set; }
            public IPStatus Status { get; set; }
        }
        static void Main(string[] args)
        {
            var ipList = new List<IPAddress>();
            //ipList.Add(new IPAddress(new byte[] { 192, 168, 1, 69}));
            for (int i = 0; i < 256; i++) {
                ipList.Add(new IPAddress(new byte[] { 192, 168, 1, (byte)i}));
            }
            while (!Console.KeyAvailable) {
                var items = SimplePing(ipList, 3, 2000).GetAwaiter().GetResult();
                Console.Clear();
                Console.WriteLine(DateTime.Now.ToString());
                foreach (var item in items) {
                    if (item.Status == IPStatus.Success) {
                        Console.WriteLine($"{item.Ip.ToString()}: {item.Status.ToString()}");
                    }
                }
                if (!Console.KeyAvailable) {
                    Thread.Sleep(5000);
                }
            }
        }
        static async Task<IEnumerable<PingResult>> SimplePing(List<IPAddress> ipList, int retryCount, int timeout)
        {
            var tasks = new List<Task>();
            var tasksResult = new ConcurrentQueue<PingResult>();
            foreach (var ip in ipList) {
                await Task.Delay(20); // без этого не кторые адресса могут не отвечать
                tasks.Add(DoPing(ip, retryCount, timeout, tasksResult));
            }
            await Task.WhenAll(tasks);
            var result = new List<PingResult>();
            while (tasksResult.TryDequeue(out PingResult pingResult)) {
                result.Add(pingResult);
            }
            return result;
        }
        static async Task DoPing(IPAddress ipAddress, int retryCount, int timeout, ConcurrentQueue<PingResult> resultQueue)
        {
            using (var ping = new Ping()) {
                while (retryCount > 0) {
                    retryCount--;
                    var result = await ping.SendPingAsync(ipAddress, timeout);
                    if (result.Status != IPStatus.Success) {
                        continue;
                    }
                    resultQueue.Enqueue(new PingResult() {
                        Ip = ipAddress,
                        Status = result.Status
                    });
                    break;
                }
            }
        }
    }
}

PS:
У сетевых железок есть функция(не знаю как нызывается, буду признателен если кто подкажет), которая может рубить пакеты если их слишком много в один момент времени(наверно это анти DDOS какой то). Что бы это обходить, в коде есть Task.Delay(20). 20 это не сакральное число, можно выбрать другое приемлемое.

Answer 2

Если интересен именно эксель, то можно из него запускать сразу несколько командных строк с командой (cmd.exe)

ping myip >> result%n%.txt

Где n - порядковый номер. И проверять результат исполнения уже из txt файла. Можно через макрос экселя запускать одновременно по 20-100 ip адресов... (по идее число неограниченно, только ресурсами машины)

Еще вариант создание BATника, в котором идёт вызов ping через команду start, что-то вроде:

start ping 1й_ip >> 1.txt
start ping 2й_ip >> 2.txt
....
start ping 100й_ip >> 100.txt

Эти 100 команд запустятся параллельно.

READ ALSO
Оформление &quot;подтекста&quot; боковыми линиями

Оформление "подтекста" боковыми линиями

Каким способом возможно реализовать такие боковые линии, используя только HTML, CSS

171
Как сделать, чтобы страница загрузилась после того как запустится скрипт js, ибо происходит мерцание?

Как сделать, чтобы страница загрузилась после того как запустится скрипт js, ибо происходит мерцание?

Изменяю css стили с помощью js, происходит мерцание при перезагрузке страницы или перелистываниии с стр на стр, можно ли страницу грузить после...

99
Как сделать видео с редактором кода

Как сделать видео с редактором кода

Недавно наткнулся на сайт freecodecamporg так вот, там есть видео и уже в видео можно редактировать код, например вот это https://www

95
обязательное поле при его отображении

обязательное поле при его отображении

есть поля выбора select из дувх значенийпри выборе одного из значения появляется доп поле

92