#c_sharp #многопоточность #ssh
Наставьте на путь истинный, подскажите, что можно сделать/почитать по этому поводу? Есть список объектов типа IP. class IP { public string host; public string login; public string password; } И метод, который перебирает этот список в параллельном цикле, в котором происходит подключение к SSH. public void Cycle() { int port = 22; Parallel.ForEach(ipList, ipObject => { string ip = ipObject.host; string login = ipObject.login; string password = ipObject.password; SshConnect(ip, port, login, password); }); } Метод SSHConnect реализован с помощью библиотеки Renci.SSHNet. Выглядит следующим образом: private bool SshConnect(string host, int port, string login, string password) { bool flag = true; try { var client = new SshClient(host, port, login, password); client.Connect(); client.Disconnect(); } catch { flag = false; } return flag; } Все бы ничего, но скорость перебора и подключения к SSH ужасно медленная. Что можно сделать, чтобы увеличить скорость? P.S. Раньше у меня был алгоритм, который работал, как минимум, в 2 раза быстрее этого. В нем я использовал один поток, в котором находился цикл, перебирающий список и в этом же потоке создавалось определенное количество других потоков, которые в свою очередь обрабатывали эти элемента списка. На другом форуме сказали, что так делать нежелательно и немного почитав, я решил попробовать Paralel.ForEach, но результат не оправдал ожиданий.
Ответы
Ответ 1
Основное время при подключении по ssh тратит не процессор, а сеть - пакет TCP SYN слишком долго идет до сервера и обратно. В таких условиях надо и правда создавать как можно больше потоков, Paralel.ForEach же ограничивает их число. У вас есть список ssh-серверов, с которыми надо что-то сделать - или вы сканируете сеть? Во втором случае можно сделать оптимизацию. Сначала можно проверить, открыт ли порт 22 - а уже потом подключаться по ssh там, где он открыт. Это можно сделать параллельно, но вовсе без потоков, при помощи асинхронного программирования: var taskList = ipList.Select(async ipObject => { try { using (var c = new TcpClient()) await c.ConnectAsync(ipObject.host, 22); retrun ipObject; } catch { return null; } }).ToArray(); Task.WaitAll(taskList); ipList = taskList.Select(task => task.Result).Where(ipObject => ipObject != null).ToList(); // Теперь в ipList остались только хосты, которые отвечают на порту 22
Комментариев нет:
Отправить комментарий