|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Создать модуль быстрого сканера портов ТСР
У меня есть код, но необходимо сделать файл .exe. Необходимо сделать так, чтобы это всё было на Форме
Сам код: Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, winsock2, ComCtrls; type TForm1 = class(TForm) Panel1: TPanel; Label1: TLabel; AddressEdit: TEdit; Label2: TLabel; StartPortEdit: TEdit; EndPortEdit: TEdit; Label3: TLabel; Button1: TButton; DisplayMemo: TRichEdit; ProgressBar1: TProgressBar; procedure Button1Click(Sender: TObject); private { Private declarations } function LookupName: TInAddr; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} //Функция преобразвывающся введённый адрес сервера в спецформат //Если введено символьное имя, то она преобразовывает его сначала в IP адрес, //а потом переводит в спец формат function TForm1.LookupName: TInAddr; var HostEnt: PHostEnt; InAddr: TInAddr; begin if Pos('.', AddressEdit.Text)>0 then InAddr.s_addr := inet_addr(PChar(AddressEdit.Text)) else begin HostEnt := gethostbyname(PChar(AddressEdit.Text)); FillChar(InAddr, SizeOf(InAddr), 0); if HostEnt <> nil then begin with InAddr, HostEnt^ do begin S_un_b.s_b1 := h_addr^[0]; S_un_b.s_b2 := h_addr^[1]; S_un_b.s_b3 := h_addr^[2]; S_un_b.s_b4 := h_addr^[3]; end; end end; Result := InAddr; end; procedure TForm1.Button1Click(Sender: TObject); var i,j,s, opt, index: Integer; FSocket: array [0..41] of TSOCKET; //Массив сокетов busy : array [0..41] of boolean; //Массив, в котором будет храниться информация о каждом сканируемом сокете port : array [0..41] of integer; //Массив сканируемых портов addr : TSockAddr; hEvent : THandle; //Объект для обработки сетевых событий fset : TFDset; tv : TTimeval; tec :PServEnt; PName:String; GInitData : TWSADATA; begin // Устанавливаю максимальное и минимальное значение полоски состояния сканирования //Я устанавливаю в минимум начальный порт сканирования, а в максимум - конечный порт ProgressBar1.Min:=StrToInt(StartPortEdit.Text); ProgressBar1.Max:=StrToInt(EndPortEdit.Text); //Инициализирую WinSock WSAStartup(MAKEWORD(2,0), GInitData); //Записываю в переменную i значение начального порта i:=StrToInt(StartPortEdit.Text); //Заполняю основные поля структуры addr, которая будет использоваться //при вызове функции connect addr.sin_family := AF_INET; addr.sin_addr.s_addr := INADDR_ANY; //Вывожу сообщение о том, что начат поиск введённого хоста DisplayMemo.SelAttributes.Color:=clTeal; DisplayMemo.SelAttributes.Style:=DisplayMemo.SelAttributes.Style+[fsBold]; DisplayMemo.Lines.Add('Поиск хоста'); //LookupName - эта функция написана выше и она возвращяет адрес в спец формате указанного сервера //Результат этой функции я записываю в поле адреса сервера структуры addr addr.sin_addr := LookupName; //Вывожу сообщение о том, что начато сканирование DisplayMemo.SelAttributes.Color:=clTeal; DisplayMemo.SelAttributes.Style:=DisplayMemo.SelAttributes.Style+[fsBold]; DisplayMemo.Lines.Add('Сканирование...'); //В index находиться количество сокетов проверяемых за один раз index:=40; //Создаю объект для обработки сетевых событий hEvent := WSACreateEvent(); while i<StrToInt(EndPortEdit.Text) do begin ///Всем элементам массива busy присваиваю значение false for j:=0 to index do busy[j]:=false; //В этом цикле будут асинхронно посылаться запросы на моединение //переменная j будет изменяться от 0 до максимального количества //элементов в массиве for j:=0 to index do begin //Если j-й порт превысил значение указанного максимального //порта, то прервать цикл if i>StrToInt(EndPortEdit.Text) then begin index:=j-1; break; end; //Инициализирую очередной j-й сокет из массива FSocket FSocket[j] := socket(AF_INET, SOCK_STREAM, IPPROTO_IP); //Добавляю j-й сокет к объекту событий с помощью WSAEventSelect //1-й параметр - Добавляемый сокет //2-й параметр - объект событий, который был создан с помощью WSACreateEvent //3-й параметр - какие события ожидать. Тут я указываю FD_WRITE - события записи и FD_CONNECT - события о заключении соединения WSAEventSelect(FSocket[j], hEvent, FD_WRITE + FD_CONNECT); //Указываем порт, на который надо произвести попытку соединения addr.sin_port := htons(i); //Попытка коннекта на очередной порт connect(FSocket[j], @addr, sizeof(addr)); //Даём ОС поработать и обработать накопившиеся события. //Если этого не делать, то вовремя сканирования будет //происходить эффект зависания Application.ProcessMessages; //Проверяю, были ли ошибки. if WSAGetLastError()=WSAEINPROGRESS then begin //Если ошибка произошла, то закрываю этот порт closesocket (FSocket[j]); //Устанавливаю соответствующий элемент в массиве busy в true //чтобы потом не проверять этот порт, потому что он всё равно //уже закрыт busy[j]:=true; end; //Указываю в массиве port, на какой именно порт мы сейчас послали запрос port[j]:=i; //Увеличиваю счётчик i в котором я отслеживаю, какой порт сейчас сканируеться //чтобы на следующем этапе цикла for запустить сканирование следующего порта i:=i+1; end; //Обнуляю переменную fset FD_Zero(fset); //Заполняю сканируемый массив сокетов в переменную fset for j := 0 to index do begin if busy[j] <> true then FD_SET (FSocket[j], fset); end; //Даём ОС поработать и обработать накопившиеся события. Application.ProcessMessages; //Заполняю структуру, в которой указано время ожидания события от сокета tv.tv_sec := 1; //Мы будем ждать 1 секунду tv.tv_usec := 0; //Ожидаем пока произойдёт хотя бы одно событие от любого из сокетов s:=select (1, nil, @fset, nil, @tv); //Даём ОС поработать и обработать накопившиеся события. Application.ProcessMessages; //Запускаю массив, в котором будет проверятся, какие из сокетов в массиве FSocket //прошли коннект успешно, а какие нет. for j := 0 to index do begin //Проверяем, был ли закрыт соответствующий порт из-за ошибки //Если да, то нет смысла его проверять if busy[j] then continue; if FD_ISSET (FSocket[j], fset) then begin //В переменную s записываеться размер перменной Opt s:=Sizeof(Opt); opt:=1; //Получаю состояние текущего j-го сокета //результат состояния будет в переменной opt getsockopt(FSocket[j], SOL_SOCKET, SO_ERROR, @opt, s); //Если opt равно 0 то порт открыт и к нему можно подключится if opt=0 then begin //Пытаюсь узнать символьное имя порта tec := getservbyport(htons(Port[j]),'TCP'); if tec=nil then PName:='Unknown' else begin PName:=tec.s_name; end; //Вывожу сообщение об открытом порте DisplayMemo.Lines.Add('Хост:'+AddressEdit.Text+': порт :'+IntToStr(Port[j])+' ('+Pname+') '+' открыт '); end; end; //Закрыть j-й сокет, потому что он больше уже не нужен closesocket(FSocket[j]); end; //Увеличивею позицию в ProgressBar1 ProgressBar1.Position:=i; end; //Закрываю объект событий WSACloseEvent(hEvent); //Вывожу сообщение о конце сканирования DisplayMemo.SelAttributes.Color:=clTeal; DisplayMemo.SelAttributes.Style:=DisplayMemo.SelAttributes.Style+[fsBold]; DisplayMemo.Lines.Add('Сканирование закончено...'); ProgressBar1.Position:=0; end; end. P.S. Это снова картинка с лабы (авторы хотели сразу указать студентам, что должно получиться в итоге) Последний раз редактировалось Admin, 05.11.2014 в 19:42. |
#2
|
||||
|
||||
А в чём хоть проблема-то? Это и так уже готовый юнит формы. Всего лишь что нужно сделать, так это открыть новый проект, накидать на форму компонентов прям по списку секции type (Panel1, Label1 etc.) заменить стандартный код на вышеприведенный и подключить к кнопке Button1 процедуру клика
Я не понял Вашего вопроса, но всё же Вам на него отвечу! |