#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
Комментариев нет:
Отправить комментарий