чем можно организовать сие мероприятие? :confused:
SysLibSockets?
п.с. просто необходимо чтобы при обрыве Ethernet параметр привязанный к пингу переходил в ноль тем самым меняя режим работы ПЛК-100, зашитый в программу
Вид для печати
чем можно организовать сие мероприятие? :confused:
SysLibSockets?
п.с. просто необходимо чтобы при обрыве Ethernet параметр привязанный к пингу переходил в ноль тем самым меняя режим работы ПЛК-100, зашитый в программу
да, именно им.
тип - Sock_dgram == 2
протокол -ipproto_icmp == 1
спасибо!
то есть это будет выглядеть так
а IPадрес и номер порта удаленной машины где нужно указывать?Код:socket:=SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_ICMP);
а величины размера (len) и адреса (buf) буфера откуда брать? :confused:
Пример пинга
Олег
спасибо.
но вопросы те же...
в sock_addr.sin_addr и sock_addr.sin_port я должен записать IP адрес и порт машины вместо 16#0A00065F и 16#0800?
так ли это?
Именно так, IP=10.0.6.95
спасибо Олег.. проработал пример под себя....все работает супер!
Супер гууууд
А можно чуть подробней: как писать IP (16#0A00065F - в таком или 10.0.6.95 в таком виде!)
и что имеется ввиду под номером порта! 16#0800
обычно пингуем без всяких портов (я имею ввиду комп виндовс, просто ип и все)
Здесь просто если со вторым ПЛК, то тогда понятно, что за порт, а вот если комп виндос то что за порт? и где его посмотреть?
16#0A00065F это в каком формате и как 10.0.6.95 перевести в этот формат
Если точнее, то я хочу ПЛК 100 пинговать компьютер с виндой
что надо ип вбить понятно а в какой форме и как недопонимаю и что с портом делать (какой вбивать)
web_stat:=1;
sock_adr.sin_addr:=16#0A00065F;
(*IP Адрес опрашиваемого устройства {создается сокет на опрашивающем устройстве}*)
sock_adr.sin_family:=SOCKET_AF_INET;
(*Стек протоколов TCP/IP*)
sock_adr.sin_port:=16#0800;
(*Старший байт- Тип ICMP пакета {08 - Ping} младший байт- код ICMP пакета { 0- Ping}*)
sock_adr1.sin_addr:=16#0A000626;
(*То же самое для функции чтения {в принципе не важно}*)
sock_adr1.sin_family:=SOCKET_AF_INET;
sock_adr1.sin_port:=16#1111;
my_BUFs:='qwertyuiopasdfghjklzxcvbnm123456';
----------------------------------------------------------------------------------
это из примера, а что править!:
вот это sock_adr.sin_addr:=16#0A00065F; тогда как переводить
и вот это sock_adr.sin_port:=16#0800; а здесь 137 как перевести
а это тоже на что то править или не надо sock_adr1.sin_addr:=16#0A000626;
sock_adr1.sin_port:=16#1111;
кажется ясно: надо 16# отбрасывать и без точек в HEXe
но вот в порту стоит впереди 0 тогда 137 будет 0089 или 89 просто!
sock_adr1.sin_addr:=16#0A000626;
sock_adr1.sin_port:=16#1111;
с этим не совсем ясно
все изменил, но ни одного положительного запроса!
(*Время ожидания истекло считываем данные*)
IF FIND(my_BUFr,'pasd')<>0 THEN
suces:=suces+1;
(*Сравниваем переданные и принятые данные в случае идентичности увеличиваем счетчик удачного Ping*)
ELSE
faul:=faul+1;
(*В противном случае увеличиваем счетчик неудачного Ping запроса*)
растет бесконечно faul:=faul+1; а suces:=suces+1; все время равно 0 куда копать!?
Правда есть еще такой параметр как sock_adr.sin_family:=SOCKET_AF_INET; - что он дает? равен 2, может его поменять, а на что тогда?
Не буду плодить темы напишу здесь. Задача та же - пинговать ПК с ОВЕНа (ПЛК110).
Как основу брал этот же пример.
Есть несколько вопросов и проблем:
1) Я правильно понимаю, что ICMP использует датаграммы (тип коммуникации SOCKET_DGRAM) и общая схема работы клиента на датаграммах такова:
1.1. создаем TCB структуру SOCKADDRESS для сервера (машины, которую будем пинговать) с нужными настройками (serv.sin_addr:= SERV_IP, serv.sin_family:=SOCKET_AF_INEТ, serv.sin_port := ICMP_TYPE_CODE)
1.2. создаем TCB структура SOCKADDRESS для клиента (ПЛК) с такими же настройками, за исключением адреса (client.sin_addr:= PLC_IP, client.sin_family:=SOCKET_AF_INEТ, client.sin_port := ICMP_TYPE_CODE)
1.3. заполняем буфер проверочными данными для отправки (например, 32 байта символов sBuf :STRING := 'abcdefghijklmnopqrstuvwabcdefghi')
1.4. делаем вызов сокета, получаем дескриптор ( sock := SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_ICMP) )
1.5. связываем сокет с адресом клиента ( bindClient := SysSockBind(sock, ADR(client), SIZEOF(client)) )
1.6. пишем буфер в сокет ( bufSend := SysSockSendTo(sock, ADR(sBuffer), 32, 0, ADR(serv), SIZEOF(serv)) )
1.7. дальше пишем в буфер приема rBuf ( recv:=SysSockRecvFrom(sock,ADR(rBuf),32,0,ADR(clie nt),SIZEOF(client)) ), выждав какой то таймаут
1.8. сравниваем содержимое переданного с принятым
?
2) Одиночный пакет с ПЛК уходит нормально, доходит до ПК, WireShark его видит. На первый взгляд с пакетом все ОК - тип 08 (эхо-запрос) , код 00. Но почему то я вижу коды 61("а") и 62 ("b") в качестве идентификатора ICMP пакета и коды 63 64 ("с" "d") в качестве порядкового номера. Это почему так? Я думал, что вся эта возня с структурами SOCKADRESS как раз и должна отделить всякие заголовки от данных из буфера.
Вложение 17606
3) Самая большая проблема сейчас - как видно с того же скрина WireShark`а ПК не хочет слать в ответ ICMP пакет. В чем дело???
4) как работает SysSockRecvFrom? Он может сколько угодно ждать ответа, проверяя буфера сокета на предмет пришедших данных при каждом цикле работы ПЛК?
Пример пинга во вложении.
Не работает (см. скриншоты). Пакеты на ПК приходят, но ПК на них не отвечает.
адрес ПЛК110-24: 10.8.11.230 (16#0A080BE6)
адрес пингуемого ПК с Windows 7: 10.8.11.104 ( 16#0A080B68)
Вложение 17620Вложение 17621
Вот мой рабочий пинг. ПЛК160 — 10.0.6.10, ПК — 10.0.6.9.
Вложение 17628
Фаервол?Цитата:
3) Самая большая проблема сейчас - как видно с того же скрина WireShark`а ПК не хочет слать в ответ ICMP пакет. В чем дело???
Как и многие другие «поточные» функции, она тут же возвращает число прочитанных байт, даже если это число равняется нулю. Очень удобно на самом деле (см. мой пример). Если, скажем, в примере от Владислава зачем-то делается задержка после отправки запроса, то я легко обхожусь без неё как раз за счёт моментального возврата SysSockRecvFrom.Цитата:
4) как работает SysSockRecvFrom? Он может сколько угодно ждать ответа, проверяя буфера сокета на предмет пришедших данных при каждом цикле работы ПЛК?
Спасибо большое за пример - хорошо структурирован. Что значит "поточные"? SysSockRecvFrom - аналог обычной recvfrom как я понимаю. Работает на дейтаграммах, без установления соединения. У Владислава сделана задержка (как я понял) для того, чтобы с учетом задержки ответа не вызывать в каждом цикле ПЛК SysSockRecvFrom.
Но Ваш вариант в общем мне больше нравится. Но ПК все равно не отвечает (см.скрин) - если это файерволл ПК, то почему обычный пинг с ПК на ПЛК проходит*. И кстати, Вас не смущает, что первые четыре байта (30 31) (32 33) приходят в поле идентификатора и порядкового номера?Вложение 17629Вложение 17630
«Поточные» в широком смысле — вместе с теми, которые пишут и читают в/из последовательного порта, например. Насколько я знаю, recvfrom блокирует поток в ожидании данных. Но я слишком давно ничего не писал голыми сокетами в нативных языках на ПК, чтобы утверждать наверняка. Это же касается и полей-идентификаторов. Полагаю, их надо заполнять вручную. Однако факт есть факт — на моей машине оно работает и с такими идентификаторами.Цитата:
Что значит "поточные"? SysSockRecvFrom - аналог обычной recvfrom как я понимаю.
Спасибо еще раз за пример. Разобрался - проблема в самом деле в брандмауэре - он пропускал только ответы на запросы встроенной в Windows утилиты ping. Ответы на ICMP пакеты других программ блокировались.
Все работает, но мне все таки странно видеть данные из буфера "данных" в качестве идентификатора...
Ну и непонятно использование структуры SOCKADDRESS - зачем у Владислава в примере задается порт sock_adr1.sin_port:=16#1111 ?
Тот, кто это писал, не понимал назначения этой структуры. В неё ничего записывать не надо, т.к. туда пишет координаты отправителя функция RecvFrom.Цитата:
Ну и непонятно использование структуры SOCKADDRESS - зачем у Владислава в примере задается порт sock_adr1.sin_port:=16#1111 ?
А кстати, в чем смысл:
IF stateTimer.ET > T#1s AND state < C_ERROR THEN
state := C_ERROR + state;
END_IF
?
И сокет не закрывается потому, что пинг бесконечный?
Там выше ещё строка есть stateTimer(IN := state = _state). С таким таймером мы знаем, в течение какого времени находимся на текущем шаге. Соответственно те строки, про которые вы спросили, переводят автомат в состояние ошибки, если мы топчемся на одном шаге дольше секунды. Например, если не дождались ответа (шаг 3), то выставляется код/состояние 203. Если по какой-то причине не смогли даже скормить ответ на отправку, то код будет 202. При отладке очень помогает. Этот же таймер и для выдерживания пауз используется (состояние SUCCESS). Ну и вообще это у меня идиома такая для конечных автоматов на ST.
Да, сокет не закрывается, потому что этот код кроме бесконечной демонстрации пинга ничего не делает.
Ну и непонятно использование структуры SOCKADDRESS - зачем в примере задается порт sock_adr1.sin_port:=16#1111 ?
Сделано это для целей отладки - видимо создатель программы по шагам проверял работу всех функций (писал не я, могу только догадываться).
P.S. Требовать от примера Ping совершенства, отсутствия синтаксического оверхеда, развёрнутых комментариев и тотальной обработки ошибок - это перфекционизм. :D
Здравствуйте!
Оформил упомянутый в теме ICMP_TEST_PING.pro в виде блока, который после 4-х подряд успешных запросов показывает что устройство в сети:
Вложение 33941
Используется ПЛК 110.60 старой серии.
Блок работает, но только когда он в одном экземпляре, что впрочем вполне ожидаемо.
По условиям задачи нужно отслеживать появление в сети 10-ти устройств с идущими подряд IP адресами, но при этом нужно знать какое именно устройство появилось в сети и какое отключилось.
Напрашивается мысль что нужно перебирать в блоке адреса по очереди, но моего опыта в ST маловато для решения подобной задачи, к тому же отлаживать приходится на "боевом" ПЛК и случаются зависания.
Подскажите пожалуйста, как примерно должен выглядеть код, реализующий такую задачу, или может быть есть другой алгоритм?