Посмотрел. Нисколько не удивлён тому, что "бибка" "Запретная плюшка" полностью неработоспособна. По очевидным причинам, изложенным мной чуть выше. Могу пройтись по всем её функциям. Если вдруг интересно, конечно.
Вид для печати
Чтобы несколько разбавить эту скучную тему, выложу код NTP-клиента. Товарищ capzap выкладывал давным-давно свою версию. Моя, пожалуй, чуть получше. Скачать проект можно здесь.
PROGRAM PLC_PRG
VAR
GetTime: CurTimeEx;END_VAR
TimeAndDate: SystemTimeDate;
Sys_Time: SysTime64;
ntp_socket : DINT:= SOCKET_INVALID;
ntp_sockaddr : SOCKADDRESS;
state: DWORD;
R_BUF: ARRAY[0..47] OF BYTE;
i: WORD;
received: DINT;
NTP_TIME: SDT;
tx, last: DWORD;
OK, ERRORS: DWORD; (* Счётчики удачных и неудачных запросов - для справки *)
VAR CONSTANT
S_BUF: ARRAY[0..47] OF BYTE := 27,47(0);END_VAR
TIMEOUT: TIME := t#500ms; (* Тайм-аут ожидания ответа ntp-сервера *)
HOME: TIME := t#5h; (* UTC+5 мой часовой пояс *)
PERIOD: TIME := t#30s; (* Время между ntp-запросами. Не менее 30 секунд! *)
ntp_port: UINT := 123;
ntp_addr: UDINT := 16#34B2A129; (* 52.178.161.41 time.windows.com *)
================================================== ===============
(* Для компиляции требуются библиотеки SYSLIBTIME, SysLibSockets и oscat_basic_333 *)
(*Читаем текущее время - здесь только для контроля правильности работы программы *)
TimeAndDate.Year :=0; TimeAndDate.Month :=0; TimeAndDate.Day :=0; TimeAndDate.DayOfWeek :=0;
TimeAndDate.HOUR :=0; TimeAndDate.MINUTE :=0; TimeAndDate.SECOND :=0; TimeAndDate.Milliseconds :=0;
TimeAndDate.dwHighMsec :=0; TimeAndDate.dwLowMSecs :=0;
Sys_time.ulHigh :=0; Sys_time.ulLow :=0;
GetTime (SystemTime:=Sys_Time , TimeDate:= TimeAndDate);
(* tx := T_PLC_MS(); *) (* Этот вариант годится, если часть программы выше отсутствует, т.е. когда нам неизвестно значение переменных структуры TimeAndDate *)
tx := TimeAndDate.dwLowMSecs;
CASE state OF
0: (* Cоздание сокета *)
ntp_socket := SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_UDP);1: (* Посылаем запрос на ntp-сервер *)
ntp_sockaddr.sin_family := SOCKET_AF_INET;
ntp_sockaddr.sin_port := ntp_port;
ntp_sockaddr.sin_addr := ntp_addr;
FOR i:=0 TO 47 DO R_BUF[i] := 0; END_FOR (* Очистка приёмного буфера *)
state := 1;
SysSockSendTo(ntp_socket, ADR(S_BUF), SIZEOF(S_BUF), SOCKET_MSG_OOB, ADR(ntp_sockaddr), SIZEOF(ntp_sockaddr));2: (* Ждём ответ ntp-сервера в течение времени TIMEOUT *)
last := tx;
state := 2;
received := SysSockRecvFrom(ntp_socket, ADR(R_BUF), SIZEOF(R_BUF), SOCKET_MSG_OOB, ADR(ntp_sockaddr), SIZEOF(ntp_sockaddr));3: (* Запись полученного времени в системный таймер*)
IF received=48 AND R_BUF[40]<>0 THEN
state := 3;ELSE
IF tx-last>TIME_TO_DWORD(TIMEOUT) THENEND_IF
ERRORS := ERRORS+1; (* Ошибки появляются только при обрыве связи *)END_IF
state := 4;
NTP_TIME:= DT_TO_SDT( DWORD_TO_DT(DWORD_OF_BYTE(R_BUF[40],R_BUF[41],R_BUF[42],R_BUF[43]) - DWORD#2208988800 + TIME_TO_DWORD(HOME)/1000));4: (* Закрываем сокет *)
TimeAndDate.Year := NTP_TIME.YEAR; TimeAndDate.Month := NTP_TIME.MONTH; TimeAndDate.Day :=NTP_TIME.DAY;
TimeAndDate.HOUR := NTP_TIME.HOUR; TimeAndDate.MINUTE := NTP_TIME.MINUTE; TimeAndDate.SECOND := NTP_TIME.SECOND;
GetTime (SystemTime:=Sys_Time , TimeDate:= TimeAndDate);
OK := OK + 1;
state := 4;
SysSockClose(ntp_socket);5: (* Ждём окончания времени между запросами *)
state := 5;
IF tx-last>TIME_TO_DWORD(PERIOD) THENEND_CASE
state := 0;END_IF
ну и зачем было выкладывать то непотребство из шестого поста, если можете нормально писать?
А по этому коду, используется
SysSockCreate
SysSockSendTo
SysSockRecvFrom
зачем остальные функции?
Работа с сокетами в неблокирующем режиме с нерабочей функцией GetLastError - это как минимум странно. Про несоответственность описания я уж и упоминать устал. Tcp-сокеты в текущей их реализации таковы, что лучше ими не пользоваться.
ЗЫ. Особенно это касается серверного режима работы.Написать клиента ещё с грехом пополам можно, написать нормально функционирующий сервер - нереально.
а веб сервер статических страниц, а у меня еще и с ajax это не нормально функционирующий сервер, а слейв модбасТСР это не нормально функционирующий сервер?
я как раз про программный, то что выкладывал здесь на форуме, правда это было по UDP с вейнтековской панелью, зато используется на производстве уже несколько лет, а не чисто потестить
Я и задаю вопрос: "Доколе?!" А в ответ тишина.. Пардон, ответ был "никто ничего "исправлять" не будет". Потом его, правда, стыдливо потерли.
Я с косяками "Овена" разобрался и по мере возможности могу их обходить, но это вот все нифига не нормально. Разговоры про то, что у всех косяки мне тоже абсолютно непонятны.
А более всего непонятно, почему бы эти косяки не исправить. При наличии исходников прошивки эту работу можно выполнить максимум за день. Во всяком случае, я за день точно исправил бы большую их часть. Даже впервые увидев эти исходники.. Что уж и говорить о разработчиках? Для них это исправление вряд ли заняло бы более 15 минут. И?
Может, там и нет такого безобразия. Кто его знает?
Долго тестировали? У меня тоже сервер будто бы работал. Но обычно не более суток. И да - про М02 ничего сказать не могу. Другой процессор, другая прошивка.
Пример рабочего кода выложить несколько проблематично. Просто все это существует в виде библиотеки для modbus, делал для себя. Если хотите могу выложить, но нет ни описаний и ни примеров. Есть только тесты.
Оно Вам надо?
Всем доброго дня!
У меня такой вопрос, есть owen ПЛК110-30, программа написана на функциональных блоках, работаем с ним по TCP отправляя регистры
Сама программа отрабатывает претензий к ней нет, но эпизодически при переподключении не можем подключиться к контроллеру.
почитав документацию выяснилось что есть ограничение по количеству созданных сокетов, а проверка их если и есть, то она по таймингам совсем не вписывается.
Собственно вопрос: есть ли возможно пример или сможете подсказать как осуществлять контроль за неиспользуемыми сокетами, в проекте который написан на ФБ.
возможно есть какая-то возможность получить список открытых сокетов, пробежаться по ним и закрыть неактивные, или что то в таком духе
я видел пример клиент\сервер, но если честно не могу сообразить как его применить в текущей программе
Вероятно мой вопрос останется без ответа или возможно меня закидют гневными словами типа учи мат часть, но так вышло что это совсем не моя тема и от связи с контроллером зависит стабильность работы приложения. Очень надеюсь на хоть какю-то помощь.