Помощь - Поиск - Пользователи - Календарь
Полная версия: Многопоточный сканер портов
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
*оля*
Здравствуйте)
Подскажите, пожалуйста, как сканирование портов разбить на потоки? Заранее спасибо)


private void btnPusk_Click(object sender, EventArgs e)
{
string myHost = System.Net.Dns.GetHostName();
string myIP = System.Net.Dns.GetHostByName(myHost).AddressList[0].ToString();
StartPort = Convert.ToInt32(numStart.Value);
EndPort = Convert.ToInt32(numEnd.Value);
Cursor.Current = Cursors.WaitCursor;
for (int CurrPort = StartPort; CurrPort <= EndPort; CurrPort++)
{
TcpClient TcpScan = new TcpClient();
try
{
TcpScan.Connect(myIP, CurrPort);
txtLog.AppendText("Port " + CurrPort + " open\r\n");
}
catch
{
txtLog.AppendText("Port " + CurrPort + " closed\r\n");
}

}
MessageBox.Show("Сканирование завершено");
Cursor.Current = Cursors.Arrow;
}

IUnknown

const int threadCount = 4; // Количество потоков
int toProcess = threadCount;
ManualResetEvent resetEvent;

public void DoIt(int start, int finish, string ip) // Функция потока
{
TcpClient TcpScan = new TcpClient();
for (int CurrPort = start; CurrPort <= finish; CurrPort++)
{
string s = "";
try
{
TcpScan.Connect(ip, CurrPort);
s = "Port " + CurrPort + " open\r\n";
}
catch
{
s = "Port " + CurrPort + " closed\r\n";
}

MethodInvoker action = delegate { txtLog.AppendText(s); }; // Синхронизация доп. потока с UI
txtLog.BeginInvoke(action);
}
if (Interlocked.Decrement(ref toProcess) == 0) // Закончился последний из toProcess потоков?
resetEvent.Set(); // Выставить событие, это будет поймано в WaitOne()
}

// Это еще один доп. поток, контролирующий те, которые проверяют порты...
// Если это сделать в обработчике OnClick кнопки, то WaitOne() будет блокировать UI-поток
// до тех пор, пока все остальные потоки не завершатся, и потом просто все результаты
// будут "выплюнуты" в textLog. Это не очень красиво, лучше сделать доп. поток,
// пускай он блокируется вызовом WaitOne(), а UI будет работать без задержек...
void MyControlThread()
{
string myHost = System.Net.Dns.GetHostName();
string myIP = System.Net.Dns.GetHostByName(myHost).AddressList[0].ToString();
int StartPort = Convert.ToInt32(numStart.Text);
int EndPort = Convert.ToInt32(numEnd.Text);

int portCount = (EndPort - StartPort + 1) / threadCount;
resetEvent = new ManualResetEvent(false);
Thread[] th = new Thread[threadCount];

for(int i = 0; i < threadCount; i++) // Запускаем столько потоков, сколько нужно
{
int s = StartPort + i * portCount; // и каждому задаем начальный/конечный порт для сканирования
int f = StartPort + (i + 1) * portCount - 1;
th[i] = new Thread(() => DoIt(s, f, myIP)); //Собственно, создание потока
th[i].Start(); // и его запуск
}
resetEvent.WaitOne(); // теперь ждем, пока всё завершится...
MessageBox.Show("Сканирование завершено");
}

void Button1Click(object sender, EventArgs e)
{
// Ну, а тут - просто запускаем контролирующий поток...
Thread thrd = new Thread(MyControlThread);
thrd.Start();
}
Все просто... smile.gif Но желательно, чтобы общее количество сканируемых портов было кратно числу потоков. Скажем, я проверял порты 200 - 263 (64 штуки), на 4-х потоках и на 8-ми...

Только не ожидай, что вывод результатов будет таким же, как и в твоем примере. Потому что тут порты проверяются совсем в другой последовательности...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.