purebasic.info

PureBasic forum
Текущее время: Чт июн 04, 2020 4:27 pm

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 14 ] 
Автор Сообщение
СообщениеДобавлено: Пт июл 17, 2009 11:26 am 
Не в сети
док
Аватар пользователя

Зарегистрирован: Ср авг 15, 2007 1:23 pm
Сообщений: 138
Откуда: с почты
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Итак, имеем пару не слишком кривых ручек и желание написать программу, осуществляющую контроль сети посредством ICMP-протокола.

Перечень функций (скопировано с MSDN):
Icmp6CreateFile - This function opens a handle on which ICMPv6 echo requests can be issued.
Icmp6ParseReplies - This function parses the reply buffer provided and returns the number of ICMP responses found.
Icmp6SendEcho2 - This function sends an ICMPv6 echo request and the call returns either immediately, if the Event or ApcRoutine parameter is non-NULL, or returns after the specified timeout.
IcmpCloseHandle - This function closes an Internet Control Message Protocol (ICMP) handle opened by IcmpCreateFile.
IcmpCreateFile - This function creates a handle on which Internet Control Message Protocol (ICMP) requests can be issued.
IcmpParseReplies - This function parses the reply buffer provided and returns the number of ICMP responses found.
IcmpSendEcho - This function sends an Internet Control Message Protocol (ICMP) echo request, and returns one or more replies.
IcmpSendEcho2 - This function sends an ICMP echo request and the call returns either immediately, if the Event parameter is non-NULL, or returns after the specified timeout.
Попробуем для начала написать нечто вроде комманды ping.
Для этого достаточно всего три функции из вышеизложенного списка
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
InitNetwork()
Addr=MakeIPAddress(10,206,1,254)
RData.s=Space(512)
RSize=32
RequestOptions.ip_option_information\ttl=30
RequestOptions.ip_option_information\tos=0
 
ReplyBuffer.s=Space(512)
ReplySize=64
Timeout=100
Handle=IcmpCreateFile_()
Debug IcmpSendEcho_(Handle,Addr,RData,RSize,RequestOptions,ReplyBuffer,ReplySize,Timeout)
Debug ReplyBuffer
Debug GetLastError_()
IcmpCloseHandle_(Handle)



Коды ошибок (оттуда же):
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
IP_SUCCESS
11000 - The status was success.
 
IP_BUF_TOO_SMALL
11001 - The reply buffer was too small.
 
IP_DEST_NET_UNREACHABLE
11002 - The destination network was unreachable.
 
IP_DEST_HOST_UNREACHABLE
11003 - The destination host was unreachable.
 
IP_DEST_PROT_UNREACHABLE
11004 - The destination protocol was unreachable.
 
IP_DEST_PORT_UNREACHABLE
11005 - The destination port was unreachable.
 
IP_NO_RESOURCES
11006 - Insufficient IP resources were available.
 
IP_BAD_OPTION
11007 - A bad IP option was specified.
 
IP_HW_ERROR
11008 - A hardware error occurred.
 
IP_PACKET_TOO_BIG
11009 - The packet was too big.
 
IP_REQ_TIMED_OUT
11010 - The request timed out.
 
IP_BAD_REQ
11011 - A bad request.
 
IP_BAD_ROUTE
11012 - A bad route.
 
IP_TTL_EXPIRED_TRANSIT
11013 - The time to live (TTL) expired in transit.
 
IP_TTL_EXPIRED_REASSEM
11014 - The time to live expired during fragment reassembly.
 
IP_PARAM_PROBLEM
11015 - A parameter problem.
 
IP_SOURCE_QUENCH
11016 - Datagrams are arriving too fast to be processed and datagrams may have been discarded.
 
IP_OPTION_TOO_BIG
11017 - An IP option was too big.
 
IP_BAD_DESTINATION
11018 - A bad destination.
 
IP_GENERAL_FAILURE
11050 - A general failure. This error can be returned for some malformed ICMP packets.
 


А теперь вопрос... Для чего все это надо? А это уже зависит от потребностей. Поигравшись с параметрами можно реализовать как пинг в многопотоке, так и слежение за доступностью определенных хостов (в моем случае задача заключается в том, чтобы логгировать доступность маршрутеров в корпоративке). Для велосипедоненавистников могу добавить: да это уже давно сделано до нас, но что мешает на этой основе придумать что-то свое?

_________________
Не грешите на погрешности перевода, если они сделаны, чего греха таить, дабы не погрешить против истины!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пт июл 17, 2009 12:08 pm 
Не в сети
профессор

Зарегистрирован: Пт фев 20, 2009 12:57 pm
Сообщений: 1828
Откуда: Алматы
Благодарил (а): 19 раз.
Поблагодарили: 51 раз.
Пункты репутации: 5
а есть какая-нить хитрая утилита, которую запускаешь - а она как предатель сдает все компьютеры, которые имеются в локальной сети, типа их количество, ip, имена? что-то типа localnetwork scanner.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пт июл 17, 2009 12:59 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Ср авг 15, 2007 1:23 pm
Сообщений: 138
Откуда: с почты
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
В смысле, средствами Пурика? Ну, если я не ошибаюсь, то это парочка ExamineIPAddresses() - NextIPAddress().

А через ICMP - Запускаешь в цикле и найденные IP куда-нибудь записываешь: на диск, в массив, да хоть на экран.

Я изначально думал запускать пинг из пурика и отлавливать результаты, но потом подумал, что это гониво, т.к. надо запустить пинг, дождаться пока он закончится, потом запустить арп и только так понять что указаному айпишнику соответствует тот мак, который мне нужен, а не какой-то левандоз. А тут - одна комманда - и дальше просто разгребаешься с содержимым буфера (а для эмуля пинга и того не надо, достаточно ненулевого ответа). Поэтому ReplyBuffer я и задал не как полновесную структуру ICMP_ECHO_REPLY, а просто строчку в 64 байта, чтобы не юзать еще и маллок.
З.Ы. Этот пример - просто начальная демка, на которой я разгребался с ICMP-шкой.

_________________
Не грешите на погрешности перевода, если они сделаны, чего греха таить, дабы не погрешить против истины!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Чт июл 23, 2009 3:41 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Ср авг 15, 2007 1:23 pm
Сообщений: 138
Откуда: с почты
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
Вот пример рабочей проги:
Есть текстовый файл "iplist.txt", в который записывается перечень АйПи-шников, по одному айпишнику на строку.
Прога последовательно их всех сканирует и результат выдает на консоль и доюавляет в конец файла "iplist.log"
прога минималистическая и без всяких проверок, код дарю. Кому интересно, терзайте, дерзайте и переделывайте.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 
;
; Взять из файла список IP-адресов и загнать их в массив
;
OpenFile(0, "iplist.txt")
Dim Address.l(500):Dim kat(4):IPCount=0
While Not Eof(0)
  ip$=ReadString(0)
  If ip$
    For k=1 To 4
      kat(k)=Val(StringField(ip$,k,"."))
    Next k
    If kat(1) And kat(4)
      address(IPCount+1)=MakeIPAddress(kat(1),kat(2),kat(3),kat(4)):IPCount+1
    EndIf
  EndIf
Wend
CloseFile(0)
Dim error.s(19)
;
;Коды ошибок:
;
 error(1)="The status was success."
 error(2)="The reply buffer was too small."
 error(3)="The destination network was unreachable."
 error(4)="The destination host was unreachable."
 error(5)="The destination protocol was unreachable."
 error(6)="The destination port was unreachable."
 error(7)="Insufficient IP resources were available."
 error(8)="A bad IP option was specified."
 error(9)="A hardware error occurred."
error(10)="The packet was too big."
error(11)="The request timed out."
error(12)="A bad request."
error(13)="A bad route."
error(14)="The time To live (TTL) expired in transit."
error(15)="The time To live expired during fragment reassembly."
error(16)="A parameter problem."
error(17)="Datagrams are arriving too fast To be processed And datagrams may have been discarded."
error(18)="An IP option was too big."
error(19)="A bad destination."
;
; Процедура инициализации
;
Structure ip_opt_inf
  TTL.b
  Tos.b
  Flags.b
  OptionsSize.l
  OptionsData.s{128}
EndStructure
Structure ip_echo_repl
  Address.l
  Status.l
  RoundTripTime.l
  DataSize.w
  Reserved.w
  Data.l
  Options.ip_opt_inf
EndStructure
Define ReqOpt.ip_opt_inf
Define ReplyBuffer.ip_echo_repl
Timeout=500
OpenFile(1,"iplist.log")
FileSeek(1, Lof(1))
OpenConsole()
InitNetwork()
Handle=IcmpCreateFile_()
;
; Главный цикл
;
For i=1 To IPCount
ReqOpt\ttl=128
RData.s=LSet("",32,"A")
Addr=Address(i)
If Not  IcmpSendEcho_(Handle,Addr,RData,32,ReqOpt,ReplyBuffer,128,Timeout)
  ;
  ; Если PING вернул ошибку
  ;
  Errno=GetLastError_()
  If Errno>=11000 And Errno<11019
    ErrorString.s=" "+error(Errno-10999)
  Else
    ErrorString="Unknown error."
  EndIf
  Print(FormatDate("%dd/%mm/%yyyy-%hh:%ii",Date())+" - from "+IPString(ReplyBuffer\Address)+ ErrorString)
  WriteString(1,FormatDate("%dd/%mm/%yyyy-%hh:%ii",Date())+" - from "+IPString(ReplyBuffer\Address)+ ErrorString)
Else
  ;
  ; Если получен ответ от другого узла
  ;
  If ReplyBuffer\Address <> Addr
     Print("Error on "+IPString(Addr)+": ")
     WriteString(1,"Error on "+IPString(Addr)+": ")
  EndIf
  ;
  ; Если PING успешен
  ;
  Print(FormatDate("%dd/%mm/%yyyy-%hh:%ii",Date())+" - from "+IPString(ReplyBuffer\Address)+" time: "+Str(ReplyBuffer\RoundTripTime)+" mc.")
  WriteString(1,FormatDate("%dd/%mm/%yyyy-%hh:%ii",Date())+" - from "+IPString(ReplyBuffer\Address)+" time: "+Str(ReplyBuffer\RoundTripTime)+" mc.")
EndIf
PrintN("")
WriteStringN(1,"")
Next i
;
; Завершающие процедуры перед выходом
;
;Input()
IcmpCloseHandle_(Handle)
CloseConsole()
CloseFile(1)


Допустим, можно добавить графический интерфейс, повесить таймер и мониторить работоспособность роутеров, маршрутеров, кисок и пр. в корпоративке. Или просто просканить всю локалку (для этого и файл со списком не нужен, просто айпишник менять, скажем, от 192.168.1.1 до 192.168.255.254)

_________________
Не грешите на погрешности перевода, если они сделаны, чего греха таить, дабы не погрешить против истины!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Чт июл 23, 2009 4:23 pm 
Не в сети
профессор

Зарегистрирован: Пт фев 20, 2009 12:57 pm
Сообщений: 1828
Откуда: Алматы
Благодарил (а): 19 раз.
Поблагодарили: 51 раз.
Пункты репутации: 5
если промежуток задать - от 192.168.1.1 до 192.168.255.254 это ж капец. предположим пинг = 1 секунда. а лучше повторять раза 4 - по 4 секунды на 1 айпи адрес - боюсь такая проверка затянется на неделю.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Чт июл 23, 2009 4:30 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Ср авг 15, 2007 1:23 pm
Сообщений: 138
Откуда: с почты
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
На практике на меньшее - дольше всего ожидание на "request timeout", тем более, никто не запрещает пустить одновременно 256 пингов каждый в своем отдельном потоке, другое дело, что если сканировать не локалку, а нэт, то нужен ОЧЧЕНЬ толстый канал.

_________________
Не грешите на погрешности перевода, если они сделаны, чего греха таить, дабы не погрешить против истины!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Сб янв 16, 2010 6:46 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Вс янв 10, 2010 1:10 pm
Сообщений: 126
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
в поиске наткнулся на эту тему. решил новую не создавать.
я не очень то разбираюсь в WinAPI и хотел бы попросить тех кто это умеет:
по выше изложенной информации нужна процедура
ping(Adress.s)
Которая возвращала бы TRUE при успешном пинге и FALSE при неудаче.
Заранее спасибо!

_________________
.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Сб янв 16, 2010 7:57 pm 
Не в сети
МОДЕРАТОР
Аватар пользователя

Зарегистрирован: Пн апр 09, 2007 4:53 pm
Сообщений: 11650
Благодарил (а): 4 раз.
Поблагодарили: 502 раз.
Ну как вариант
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
InitNetwork()
 
Procedure.s SendData(Connect, Command.s)
Protected Result.s="", Count=0
 Command=Command+Chr(13)+Chr(10)
 SendNetworkData(Connect, @Command, Len(Command))
 Repeat
   Delay(20)
   If NetworkClientEvent(Connect)=#PB_NetworkEvent_Data
      *mem=AllocateMemory(10000)
        If *mem
          ReceiveNetworkData(Connect,*mem,10000)
          In.s=PeekS(*mem)
          FreeMemory(*mem)
          Result=Result+In
        EndIf
   EndIf
   Count+1
 Until Count>=40
ProcedureReturn Result
EndProcedure
 
 
 
Connect=OpenNetworkConnection("www.purebasic.info", 80)
If Connect
  Delay(50)
 Otvet.s= SendData(Connect, "ping")
 CloseNetworkConnection(Connect)
EndIf
 
If OpenWindow(0, 0, 0, 600, 300, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    WebGadget(0, 10, 10, 580, 280, "")
    SetGadgetItemText(0,#PB_Web_HtmlCode,Otvet)
    Repeat
    Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf


Правда, тут команда отправляется не совсем по правилам, но думаю смысл понятен.

_________________
Компьютер позволяет решать все те проблемы, которые до его изобретения не существовали. :) :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Сб янв 16, 2010 9:04 pm 
Не в сети
МОДЕРАТОР

Зарегистрирован: Вт дек 05, 2006 8:46 am
Сообщений: 6609
Благодарил (а): 34 раз.
Поблагодарили: 230 раз.
Пункты репутации: 61
Ещё вариант, по правилам, на API:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
InitNetwork()
 
Procedure ping(in_ip.s)
  Protected *host.hostent, ret.l
  host.s = in_ip
  *host = gethostbyname_(host)
  If *host
    ret = PeekL(PeekL(*host\h_addr_list))
  Else
    ret = *host
  EndIf
  sel_ip = ret  
  ResultSize.l = SizeOf(ICMP_ECHO_REPLY) + 255
  *Result = AllocateMemory(ResultSize)
  *Echo.ICMP_ECHO_REPLY = *Result
 
        hFile.l = IcmpCreateFile_()
       
       lngResult.l = IcmpSendEcho_(hFile, sel_ip, Space(255), 255, 0, *Result, ResultSize, 2000)
       If lngResult
          ProcedureReturn #True
       Else
          ProcedureReturn #False
       EndIf
 
      IcmpCloseHandle_(hFile)
   FreeMemory(*Result)
 
EndProcedure
; ******** Проверка функции*********
 
If ping ("www.google.com")
 Debug " Успешно"
 Else
 Debug " Не пингуется!"
EndIf
 


_________________
read-only ¯\_(ツ)_/¯


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Сб янв 16, 2010 9:32 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Вс янв 10, 2010 1:10 pm
Сообщений: 126
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
kvitaliy писал(а):
Ещё вариант, по правилам, на API

Спасибо! То что надо! =)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт фев 16, 2010 2:43 pm 
Не в сети
док
Аватар пользователя

Зарегистрирован: Вс янв 10, 2010 1:10 pm
Сообщений: 126
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
И снова я :) Помогите пожалуйста со следующей задачкой:
Нужна процедура для проверки порта на удаленной машине. Синтаксис:

CheckPort(Addr.s, Port.l, Time.l)

Где Addr.s - адрес удаленной машины, Port.l - порт на удаленной машине, Time.l - максимальное время ожидания ответа.

Если удалось подключиться к указанному порту за время Time.l то процедура возращает True, иначе False.

_________________
.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Чт апр 15, 2010 10:41 am 
Не в сети
ассистент

Зарегистрирован: Ср мар 31, 2010 10:35 am
Сообщений: 20
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Пункты репутации: 0
kvitaliy писал(а):
Ещё вариант, по правилам, на API:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
InitNetwork()
 
Procedure ping(in_ip.s)
  Protected *host.hostent, ret.l
  host.s = in_ip
  *host = gethostbyname_(host)
  If *host
    ret = PeekL(PeekL(*host\h_addr_list))
  Else
    ret = *host
  EndIf
  sel_ip = ret  
  ResultSize.l = SizeOf(ICMP_ECHO_REPLY) + 255
  *Result = AllocateMemory(ResultSize)
  *Echo.ICMP_ECHO_REPLY = *Result
 
        hFile.l = IcmpCreateFile_()
       
       lngResult.l = IcmpSendEcho_(hFile, sel_ip, Space(255), 255, 0, *Result, ResultSize, 2000)
       If lngResult
          ProcedureReturn #True
       Else
          ProcedureReturn #False
       EndIf
 
      IcmpCloseHandle_(hFile)
   FreeMemory(*Result)
 
EndProcedure
; ******** Проверка функции*********
 
If ping ("www.google.com")
 Debug " Успешно"
 Else
 Debug " Не пингуется!"
EndIf
 



хы, непашет :lol:
возвращает "не пингуется" хотя всё пингуется через командную строку!


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Пн апр 20, 2020 3:01 pm 
Не в сети
док

Зарегистрирован: Пн сен 27, 2010 10:30 am
Сообщений: 154
Откуда: Уренгой
Благодарил (а): 4 раз.
Поблагодарили: 10 раз.
Пункты репутации: 5
Есть одна непонятка. Если пинговать выключенное устройство (т.е. ip адрес реальный), то IcmpSendEcho_ не всегда возвращает ноль, как будто ответ получает. Параллельно запускал ping в командной строке, обратил внимание, что если ответ "Превышен интервал ожидания для запроса", то IcmpSendEcho_ возвращает ноль, а если "Ответ от хх.хх.хх.хх: Заданный узел недоступен.", то единицу. Кто-нибудь может подсказать, как сделать адекватный пинг?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: Вт апр 21, 2020 9:29 am 
Не в сети
док

Зарегистрирован: Пн сен 27, 2010 10:30 am
Сообщений: 154
Откуда: Уренгой
Благодарил (а): 4 раз.
Поблагодарили: 10 раз.
Пункты репутации: 5
Вопрос снят, нашел решение.
Нужно просто проверить размер возвращенных в буфер данных.
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
Procedure Ping(IPv4.l, TimeOut=1000)
Protected hFile = IcmpCreateFile_()
Protected Res
Protected *|/2/>Out.ICMP_ECHO_REPLY = AllocateMemory(SizeOf(ICMP_ECHO_REPLY) + 32)
If IcmpSendEcho_(hFile, IPv4, "@Echo this stuff", 32, 0, *|/2/>Out, MemorySize(*|/2/>Out), TimeOut)
  Res = *|/2/>Out\RoundTripTime
  If *|/2/>Out\DataSize<> 32 ; проверка размера
    Res = -1
  EndIf  
Else
Res = -1
EndIf
IcmpCloseHandle_(hFile)
FreeMemory(*|/2/>Out)
 
ProcedureReturn Res
EndProcedure
 
 
; ping google DNS server
 
Repeat
  Debug Ping(MakeIPAddress(193,168,0,40))
 
  Delay(1000)
 
ForEver
 
 



Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 14 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group (блог о phpBB)
Сборка создана CMSart Studio
Русская поддержка phpBB