PDA

Просмотр полной версии : SysSockCreate



pavelrer
22.10.2013, 13:07
Добрый День
Вот такой вопрос.
Необходимо поднять tcp сервер на плк 150
Создаю проект
Кидаю туда строку
diSocket:=SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_UDP);
(тут просто udp, не важно)
так вот diSocket всегда -1, тоесть как я понимаю Ложь.
В обратном случаи все должно быть 0 или больше нуля.
diSocket нужен для других функций, не пойму почему он всегда -1.
И в эмуляторе и в контроллере?
В чем может быть дело?

Спасибо.

lazy
22.10.2013, 14:03
в ПЛК может быть открыто только 15 сокетов (соединений) соотв. SysSockCreate возвращает номер сокета (от 1 до 15). Открыв 15 штук будет всегда возвращать -1. Уже открытые сокеты нужно обязательно закрывать либо ресетнуть ПЛК.
Попробуй чонть типа:

diSocket : DINT := SOCKET_INVALID;

IF diSocket = SOCKET_INVALID THEN
diSocket := SysSockCreate( SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_UDP);
END_IF

pavelrer
22.10.2013, 23:30
DINT := SOCKET_INVALID

В примере видел это но не понимаю dint это число причем тут SOCKET_INVALID?

Объясните плиз, я програмист но этого не пойму, все примеры перекурил все одно.

Допустим в BECK там все тоже самое но справлялся числом 0 или более нуля.

Спасибо.

(новичек)

lazy
23.10.2013, 09:11
SOCKET_INVALID - константа уже объявленная в SysLibSockets.lib :
SOCKET_INVALID: DINT:=-1;
так что все ок )

pavelrer
23.10.2013, 12:00
Неподумал - Спасибо.
Так ну как я понимаю делать надо так при загрузке,старте и.т.д навсяк случай убиваем все сокеты.
потом уж создаем новый.
Но допустим такая ситуация: Мы создали экземпляр сокета все ок, а потом он у нас слетел не известно по каким причинам.
Был экземпляр с di = 1, создали новый он уже получился с di = 2, потом и этот слетел ну и так до 15.
Что будет после 15 ого создания т.е на 16ом di опять станет = 1 или будет глюк?
Или что-то еще надо прикрутить?

Cgfcb,j

pavelrer
23.10.2013, 15:13
при старте делаю так CloseSocket:= SysSockClose(0);
plc отваливается напрочь, надо сбрасывать.
ну да ладно
дальше так CloseSocket:= SysSockClose(1); до CloseSocket:= SysSockClose(15);
diSocket становиться = 16.
Интересно почему 16 а не в пределах от 1 до 15
если закрыть при старте от 1 до 16 diSocket = 16 возможно 16 экземпляров? или 1 не считается?

pavelrer
23.10.2013, 18:00
Ну вроде все нормально.
Дошел до
lResult:=SysSockListen(diSocket, 1);

Код
(* Начинаем запускать сокет сервер *)
(* Если diSocket = -1 = SOCET_INVALID т.е сокета нет то поднимаем сокет *)
IF diSocket = SOCKET_INVALID THEN
diSocket := SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_TCP);
(* SysSockCreate(SOCKET_AF_INET, SOCKET_DGRAM, SOCKET_IPPROTO_UDP) = UDP *)
(* SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_TCP) = TCP *)
(* SysSockCreate(SOCKET_AF_INET,SOCKET_DGRAM,SOCKET_I PPROTO_ICMP) = ICMP *)
END_IF

(* Если сокет поднят *)
IF diSocket <> SOCKET_INVALID THEN
(* Че-то тут настраиваем *)
oResult:=SysSockSetOption(diSocket, SOCKET_SOL, SOCKET_SO_REUSEADDR, ADR(dwValue), SIZEOF(dwValue));
diSockAddrSize.sin_family:=SOCKET_AF_INET;
diSockAddrSize.sin_addr:=SOCKET_INADDR_ANY;
diSockAddrSize.sin_port:=SysSockHtons(uiPort);
(* Связываем с сокетом локальным адресом *)
bResult:=SysSockBind(diSocket, ADR(diSockAddrSize), SIZEOF(diSockAddrSize));

IF bResult = FALSE THEN
diSocket:=SOCKET_INVALID;
END_IF
(* Объявляем о желании принять запросы на соединение *)
lResult:=SysSockListen(diSocket, 1); (* Максимальное кол-во клиентов в очереди *)
END_IF

Все TRUE а вот lResult:=SysSockListen(diSocket, 1); всегда FALSE.

В чем может быть беда?

Спасибо

pavelrer
23.10.2013, 18:25
Есть что путное ответить? Или так на форуме сидишь, да воздух сотрясаешь?
Посмотри сколько у меня сообщений, контроллер второй день на руках!
Не можешь помочь или ссылку кинуть – иди покури, расслабься, жене позвони!
Че писать то попусту, время много?
Может я не нашел, или не понял, потому и пишу, для этого форумы в общем и создают!
Извини за резкость, готовность неделя – нужна помощь а не бабкины семечки на скамеечки.

pavelrer
23.10.2013, 20:25
Еще раз извиняюсь за резкость.

Эту тему я прочел, и все остальные, перекурил все исходники НО.
Начиная от того что я не понимаю зачем валить все сокеты в начале, - это бред согласитесь, их еще нет.
Как здравому человеку в голову придет такая мысль?
А объяснять что это не виндовоз, и тут все ограничено это глупость.
Тем более если контроллер сетевой, и сетевой обмен есть, да и функции есть наверное это должно работать
нормально а не через …. Думаю это не трудно – совсем не трудно.

В хелпах нет ничего – описания slibsocket вообще нет как такового.
Вот из темы
Вообще на ПЛК 100.K-M можно создать 15 сокетов и SysSockCreate последовательно будет возвращать числа (манипуляторы или дескрипторы) от 1 до 15.
Супер наблюдал уже 16!?

Вот ваше сообщение:

думаю пример докажет, что соединение ТСР можно устанавливать и оно работает, без глубоких знаний работы сокетов, весь пример собран на библиотеках OSCAT и S3 в свободном доступе, есть нюансы касательно овен-овских контроллеров, но они были озвучены техподдержкой на форуме уже давно

Ну и что? Работать то она работает, содрана по чуть-чуть и все. А ход процесса не объясняет. В общем пусть работает
как есть просто хочется чтобы мой продукт работал нормально – просто отлично, и я его мог поддерживать и понимал
где косяки(особенности) плк, чтоб хот как-то их обойти.

“нюансы касательно овен-овских контроллеров, но они были озвучены техподдержкой на форуме уже давно”
А не подскажете где эти нюансы? Может они решили бы все мои проблемы, а то по заявлению овна – можно все,
блин – точно можно? А мультикаст работает?

Вот если прочесть это:

я делал веб-сервер и пять компов подключалось к ПЛК, получал на каждом нужную информацию и меня не заботила реализация. Такие организации как oscat и S3 не самоучки, которые выложили свои примеры, этот код протестирован и раз уж они его представили, значит он будет работать в среде CoDeSys

Для меня это не понятно, меня заботит реализация, и как это работает. Чтоб понимал лично я и отвечал лично я за свою работу.

Ну это все лирика говорящая о том что на форуме я не нашел ни какой идеи описания что работает как должно, а на что надо закрывать глаза.

Вот код который есть во всех примерах

IF diSocket <> SOCKET_INVALID THEN
SysSockSetOption(diSocket, SOCKET_SOL, SOCKET_SO_REUSEADDR, ADR(dwValue), SIZEOF(dwValue));
sa.sin_family:=SOCKET_AF_INET;
sa.sin_addr:=SOCKET_INADDR_ANY;
sa.sin_port:=SysSockHtons(uiPort);
bResult:=SysSockBind(diSocket, ADR(sa), SIZEOF(sa));
IF bResult = FALSE THEN
diSocket:=SOCKET_INVALID;
ELSE
bResult:=SysSockListen(diSocket, diMaxConnections);
IF bResult = FALSE THEN Так у меня всегда FALSE!!!!!!!!!!!!!!!!!!!
diSocket:=SOCKET_INVALID; Тут мы что получим вечно поднимающийся сокет!!???
END_IF
END_IF
END_IF

Вот и весь вопрос – почему так а не иначе?

А вот еще кусочек кода с темы

res:=SysSockBind(sock,paddr,SIZEOF(tcp_adr));
res:=SysSockListen(sock,1);

Да не хочу я делать так! Мне принципиально знать на каком этапе что отвалилась. А то глупость получается
Ой программка то не работает..

Наверное мой вопрос должен был звучать так
Почему у меня SysSockListen(diSocket, diMaxConnections); все время FALSE (-1).
Что-то делаю я не правильно или это особенность.
Если я косячу, если можно подскажите где копать.
Если особенность – как себя ведет, как с ней бороться.

На форуме к сожалению не нашел ответ на мой вопрос, нашел только то что все кто пытался что-то сделать просто
забивал на то или иное или перестраивал концепцию – вот и все. Возможно я плохо ищу или читаю с право на лево.

Спасибо.

capzap
23.10.2013, 21:07
IF bResult = FALSE THEN Так у меня всегда FALSE!!!!!!!!!!!!!!!!!!!в овеновских плк1хх должно быть не так, у меня это выглядит таким образом
bResult:=SysSockListen(diSocket, diMaxConnections);
IF bResult < 0 THEN
diSocket:=SOCKET_INVALID;
END_IFпочему у Вас всегда -1, ну незнаю, при тестировании этих соединений ни при каких обстоятельствах нельзя останавливать плк не закрыв открытые сокеты, лимит в количестве 15 быстро заканчивается в таких случаях. К тому же когда говориться о пятнадцати это совсем неозначает, что они должны быть от единицы до 15. Кто то предлагает по включению контроллера закрыть теоретически открытые сокеты, я в это неверю. Так же еще один миф, плк это не ПК поэтому один сокет - одно соединение, обойти это можно но в развлекательных целях, в пром.автоматике на это лучше не надеятся. По поводу уверенности, я допускаю что где то могут хорошо преподавать вычислительные системы и телекоммуникации, поэтому появляются дотошные пользователи-теоретики, тут я помочь ни чем немогу, я практик у меня всё работает

pavelrer
24.10.2013, 18:45
bResult:=SysSockListen(diSocket, diMaxConnections);
IF bResult < 0 THEN
diSocket:=SOCKET_INVALID;
END_IF

Это помогло, Спасибо
Но все ровно я не понял в чем разница.

По поводу дотошности, дело в том что задача стоит массовая и чем меньше всяких
косяков тем будет проще все это дело обслуживать.

“ни при каких обстоятельствах нельзя останавливать плк не закрыв открытые сокеты”
Что это значит?

Дмитрий Артюховский
24.10.2013, 19:45
bResult - ниразу не логического типа... многие библиотеки овен портировал свободно обращаясь с типами

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

кстати, при подключении через юзернет при отладке у вас на 3 сокета меньше....

pavelrer
24.10.2013, 19:57
“и получается программа работает, не работает.. с утра (после включения питания) опять работает - не работает ....”

Вот такая чача и происходит.

“поэтому вставьте блок закрытия сокетов, не морочясь проверкой результатов..”

Думал о этом, только немогу понять куда вставить закрытия сокетов, к событиям чтоль прикрутить?

Спасибо.

capzap
24.10.2013, 20:19
Думал о этом, только немогу понять куда вставить закрытия сокетов, к событиям чтоль прикрутить?

Спасибо.

по биту питания из модуля статистики запускаете закрытие сокетов

pavelrer
24.10.2013, 20:59
Модуль статистики – прикольная штука – спасибо

Так ну вот вроде SysSockListen заработал
Но теперь мой дискрипшен diSocket скачет раз в секунду то 1 то -1 других значений пока нет.
Вот чего я и боялся, может я че не понимаю?

Вот еще вопросик может я не все закрываю, я просто крою сокеты от 1..15.
Как уже писали выше действительно ну о почему дескрипшин должен быть в этом диапазоне.
Т.е вопрос простой как задавить все сокеты типа одной строкой?

Понял что закрытия сокетов при старте нужно принять как есть и все.
А в каких случаях еще необходимо закрывать сокеты?

... многие библиотеки овен портировал свободно обращаясь с типами
Не могу понять почему так, ну до ладно подставляя места FALSE и TRUE - <0 и >0 все встает на свои места.

capzap
24.10.2013, 21:29
я вообщето имел ввиду по заднему фронту питания закрывать сокеты, т.е. по выключению плк а не при старте
почему меньше нуля, потому что когда писалась ОС плк, закралось неточность, поэтому и получается что фальш это -1, а всё остальное истина
Я не пойму почему речь о каких то цифрах, закрывать Вы должны те сокеты, которые открыты и в проекте имеются на них дескрипторы

lazy
27.10.2013, 14:45
TYPE SOCKET_OPTIONS :
STRUCT
bEnable: BOOL;
bServer: BOOL;
yOutAddr1: BYTE;
yOutAddr2: BYTE;
yOutAddr3: BYTE;
yOutAddr4: BYTE;
wOutPort: WORD;
wMyPort: WORD;
END_STRUCT
END_TYPE

TYPE SOCKET_CONDITION :
(
STC_EXPECT := 2#00000,
STC_SETUP := 2#00001,
STC_CONECT := 2#00010,
STC_WORK := 2#00100,
STC_BREAK := 2#01000,
STC_CLOSE := 2#10000
);
END_TYPE


FUNCTION_BLOCK fbSocket

VAR_INPUT
i_bWrite: BOOL;
i_dwSize: DWORD;
i_pBuffer: POINTER TO ARRAY [0..MB_BUFFERSIZE_] OF BYTE;
i_pOptions: POINTER TO SOCKET_OPTIONS;
END_VAR

VAR_OUTPUT
o_dnRes: DINT;
o_eCondition: SOCKET_CONDITION;
END_VAR

VAR
m_yDelay: BYTE;
m_dnSocket: DINT := SOCKET_INVALID;
m_SAddress: SOCKADDRESS;
END_VAR



(* cycle *)

CASE o_eCondition OF

STC_EXPECT:
IF i_pOptions^.bEnable
AND m_dnSocket = SOCKET_INVALID THEN
m_dnSocket := SysSockCreate( SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_IP );
END_IF
IF m_dnSocket <> SOCKET_INVALID THEN
IF i_pOptions^.bServer THEN
o_eCondition := STC_SETUP;
ELSE
o_eCondition := STC_CONECT;
END_IF
END_IF

STC_SETUP:
m_SAddress.sin_family := SOCKET_AF_INET;
m_SAddress.sin_addr := SOCKET_INADDR_ANY;
m_SAddress.sin_port := SysSockHtons( i_pOptions^.wMyPort );
IF SysSockBind( m_dnSocket, ADR( m_SAddress ), SIZEOF( m_SAddress ) ) THEN
o_eCondition := STC_CONECT;
ELSE
o_eCondition := STC_CLOSE;
END_IF

STC_CONECT:
IF ( m_yDelay MOD 50 ) = 0 THEN
IF i_pOptions^.bServer THEN
o_dnRes := BOOL_TO_DINT( SysSockListen( m_dnSocket, 1 ) );
ELSE
m_SAddress.sin_family := SOCKET_AF_INET;
m_SAddress.sin_port := SysSockHtons( i_pOptions^.wOutPort );
m_SAddress.sin_addr := SHL( SHL( SHL(
BYTE_TO_DWORD( i_pOptions^.yOutAddr1 ), 8 )
OR BYTE_TO_DWORD( i_pOptions^.yOutAddr2 ), 8 )
OR BYTE_TO_DWORD( i_pOptions^.yOutAddr3 ), 8 )
OR BYTE_TO_DWORD( i_pOptions^.yOutAddr4 );
o_dnRes := BOOL_TO_DINT ( SysSockConnect( m_dnSocket, ADR( m_SAddress ), SIZEOF( m_SAddress ) ) );
END_IF
IF o_dnRes = 0 THEN
o_eCondition := STC_WORK;
END_IF
END_IF
m_yDelay := m_yDelay + 1;

STC_WORK:
IF i_bWrite THEN
o_dnRes := SysSockSend( m_dnSocket, i_pBuffer, i_dwSize, 0 );
ELSE
o_dnRes := SysSockRecv( m_dnSocket, i_pBuffer, i_dwSize, 0 );
END_IF

STC_BREAK:
o_dnRes := BOOL_TO_DINT ( SysSockShutdown( m_dnSocket, 2 ) );
IF o_dnRes = 1 THEN (* здесь не уверен, может быть > 0 методически грамотней *)
o_eCondition := STC_CLOSE;
END_IF

STC_CLOSE:
o_dnRes := BOOL_TO_INT( SysSockClose ( m_dnSocket ) );
IF o_dnRes = 0 THEN
m_dnSocket := SOCKET_INVALID;
o_eCondition := STC_EXPECT;
END_IF

END_CASE

конец FB

+ действие ReOpen: правой кнопкой на FB -> добавить действие
если связь пропала делаем "сокет".ReOpen;

(* reopen *)
IF m_dnSocket <> SOCKET_INVALID THEN
o_eCondition := STC_BREAK;
END_IF

кста. один сокет - одно подключение. такого понятия как "слушающий сокет" у сервера нет. в ПЛК "сервер" это просто "ведомый" или slave. он тупо отвечает на запросы клиента. поэтому если клиентов предполагается несколько то придецо создавать столько же сокетов серверов. с разными адресами (или портами) )
насчет закрывать все сокеты до отключения ПЛК - фигня. открываю при включении и закрываю чтобы открыть вновь при потере связи. кста. по ходу при этом должен открыцо с таким же номером. иначе связь не востанавливаецо.

дерзай. у меня все работает )

pavelrer
05.11.2013, 13:19
Господа разжуйте мне пожалуйста следующие.

Описание – что делаю.
ОВЕН должен выступать как сервер, работать так: соединения.
Если если готово, ждем пакет, отвечаем на него.
Написал клиента, на другой системе, ONLINE на клиенте добился только
Когда поменял в конфигурации задач выполнения сервера с T#10ms на T#100ms.
Хотя T#10ms я честно содрал из екземпла.
Так вот что надо делать после SysSockListen.
На неделе был в Москве на выстовке, там программист мне сказал что надо сделать какойто
aKnowledge ( принять соединения, разрешить обмен ). Ну а потом через прием передачу пакетов TCP.

aKnowledge – что это? И с чем его едят?

Ну или

STC_WORK:
IF i_bWrite THEN
o_dnRes := SysSockSend( m_dnSocket, i_pBuffer, i_dwSize, 0 );
ELSE
o_dnRes := SysSockRecv( m_dnSocket, i_pBuffer, i_dwSize, 0 );
END_IF

i_bWrite – это что такое, не могу понять.

Спасибо.

lazy
05.11.2013, 17:42
сначала сокет нужно открыть. для этого скармливай ему настроенный SOCKET_OPTIONS пока o_eCondition не станет STC_WORK.
"сокет"( i_pOptions := адрес на структуру SOCKET_OPTIONS );

ну а потом хош читай хош пиши.
вызов для чтения:
"сокет"( i_bWrite := FALSE, i_pBuffer := адрес буфера, i_dwSize := длинна данных );
для записи:
"сoкет"( i_bWrite := TRUE, i_pBuffer := адрес буфера , i_dwSize := длинна данных );

после вызова контролируй o_dnRes; Должен быть равным длинне данных.

если ПЛК сервер. то он должен постоянно читать и прочитав какуюнть команду от ведомого должен ее выполнить. например передать данные или наоборот записать. Это уже протокол обмена. У модбаса например есть описанный протокол. Чота типа этого (это в буфере будет лежать при чтении с сокета) полностью в нете нарыть можно:


байт 0: идентификатор транзакции - копируется сервером - обычно 0
байт 1: идентификатор транзакции - копируется сервером - обычно 0
байт 2: идентификатор протокола = 0
байт 3: идентификатор протокола = 0
байт 4: поле длины (старший байт) = 0 (так как все сообщения меньше 256)
байт 5: поле длины (младший байт) = количество следующих байтов
байт 6: идентификатор устройства (раньше "адрес SLAVE")
байт 7: код функции MODBUS
байт 8: данные, если требуется

Можешь его использовать. А можешь свой написать )

pavelrer
05.11.2013, 22:37
SOCKET_OPTIONS

Вызываю после diSocket := SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_TCP);
Если diSocket не инвалид

dwValue: DWORD:= 1;

OpResult:=SysSockSetOption(diSocket, SOCKET_SOL, SOCKET_SO_REUSEADDR, ADR(dwValue), SIZEOF(dwValue));

Что значит SysSockSetOption не то-что понять не могу, почитав доку даже додумать не смог! Что это?
Содрал тупо из екземпла.

Из доки
SysSockSetOption
Функция (из библиотеки SysLibSockets.lib) типа BOOL , вызывает функцию getsockopt операционной системы для задания определенных опций сокета. Детальное описание функции getsockopt дано в справочной системе соответствующей ОС. Возвращает TRUE при успешном окончании, иначе FALSE.

Переменная Тип данных Описание
diSocket DINT Дескриптор сокета, возвращаемый SysSockCreate (в Win32 параметр s)
diLevel DINT Специфический уровень протокола (в Win32 параметр level)
diOption DINT Имя опции. (в Win32 параметр optname) зависит от ОС
diOptionValue DWORD Значение опции; для деактивации логических значений используется "0" (в Win32 параметр optval)
diOptionLength DWORD Размер буфера значения опции (в Win32 параметр optlen)
Что это?

Специфический уровень протокола – это как – таймер, таймер времени, для отсчета временного диапазона, для задержки времени, если в вашей программе потребуется таймер. Внимание это таймер времени в формате времени и даты……Тут восход, закат и типы данных из Греции…..и.т.д – Непонятно! Такое впечатления что я с китайского перевел на итальянский потом на немецкий затем на иврит и потом на русский (ну и переводчики на русский работали в роснано).

Можно пояснить, Что такое SysSockSetOption и все его трепуха кроме diSocket

Далее еще раз

STC_WORK:
IF i_bWrite THEN
o_dnRes := SysSockSend( m_dnSocket, i_pBuffer, i_dwSize, 0 );
ELSE
o_dnRes := SysSockRecv( m_dnSocket, i_pBuffer, i_dwSize, 0 );
END_IF

i_bWrite – это что такое, не могу понять, как изменяется.
Ладно возможно туплю IF i_bWrite THEN что значит, не с чем не сравнивается?
Ну и ELSE потом. Видимо енто BOOL – false или true?

В общем возможно в данной структуре не понимаю как работает IF без сравнения
Ну и в любом случаи не понимаю как, по какому признаку меняется i_bWrite
Оно же i_bWrite: BOOL; в примере не нашел как меняется т.е всегда при старте true.

Сори за дотошность (опыта = 0, дело сделать надо понимаючи).
Курю исходники (екземплы) – понимаю все пошагово.

Спасибо.

capzap
05.11.2013, 22:56
может это как то поможет http://www.owen.ru/forum/showthread.php?t=12729&p=83833&viewfull=1#post83833

брал код отсюда http://www.owen.ru/forum/showthread.php?t=12947&p=85927&viewfull=1#post85927

lazy
06.11.2013, 10:16
Результатом выполнение любого действия заключенного между "IF" и "THEN" будет булевая переменная равная TRUE или FALSE. Поэтому внутри IF THEN достаточно одной переменной типа BOOL. Вощем IF i_bWrite = TRUE THEN - масло масленое (лишняя операция & индусский подход ) :)

Когда сокет открылся (o_eCondition = STC_WORK) любой вызов этого сокета приводит к чтению (при i_bWrite = FALSE) или записи (i_bWrite = TRUE) эту переменную выставляешь по желанию в вызывающем сокет коде.

у меня TCP IP поднялся без дополнительных настроек SysSockSetOption. поэтому думаю на нее можно забить. если канеш не знаешь точно что от нее хочешь )

pavelrer
06.11.2013, 19:34
Ну пока до обмена пока видно далеко….

Вот какая штука происходит.
ОВЕН будет сервером. Клиентом железка со своей средой под юниксообразом.
На клиенте создаю соединение турум пумпум тыкаюсь в ip и порт овна.
Эврика клиент показывает ONLINE.
Дальше чудеса останавливаю, сбрасываю или выдергиваю из овна патчкорд – Клиент усеровно ONLINE.
Ладно думаю руки крюки в клиенте дровишки где-то неправильно написал.
Ставлю на клиенти дровишки под другую железку не ОВЕН, меняю в них порт и ip на те что в ОВНЕ.
Эврика опять мой клиен кричит ONLINE. Выдеркиваю патчкорд из ОВНА – опять ONLINE.
Ну думаю как так, беру железку к которой был приделан измененный драйвер подключаю к сети,
В дровишках меняю ip и порт обратно. Клиент ONLINE. Выдергиваю патчкорд из железки – Клиент OFFLINE.

Что за чудеса? Есть у кого мысли?

capzap
06.11.2013, 19:52
Вы бы меньше использовали сленг, чтоб Вас понять можно было.
Драйвер написан под сетевую карту, под стек ТСР или просто используете готовые библиотеки чтоб установить соединение?

pavelrer
06.11.2013, 22:13
Железка представляет из себя что-то типа контроллера со своей средой программирования на lua.
В ядро железки не залезть, ну и естественно драйвер писался теми средствами который дал
разработчик.
Создать соединение, коннект к порту, дисконект, закрыть соединения, ну и данные туда –суда, контроль ONLINE-OFFLINE. Все.
Наверное ответ такой - просто используете готовые библиотеки чтоб установить соединение.

Вот еще какая закономерность если на ОВЕН ставлю выполнение своего сервера менее 50ms, на клиенте
ONLINE появляется очень редко – мельком, Если ставлю более 50ms то при подключении ONLINE приходит через
5-10секунд после подключения потом всегда ONLINE, далее OFFLINE могу добиться только переустановкой драйвера
на клиенте или перезагрузкой клиента.

capzap
06.11.2013, 22:30
так спросили бы у разработчика, как он организовал контроль, может он периодически посылает на железку какие нибудь импульсы и железка на них отвечает, поэтому при разрыве четко отслеживается контроль соединения, а ОВЕНовский плк этого не понимает, потому что нереализована ответная часть

pavelrer
06.11.2013, 22:43
Разработчик в США, пошлем меня на ... как узнает что я прикручиваю к его железки более перспективные и более дешевые чем родные.
Да и так пошлет, у них там других дел по самое немогу.

может он периодически посылает на железку какие нибудь импульсы и железка на них отвечает, поэтому при разрыве четко отслеживается контроль соединения

Да не знаю, мы уж стока дровишек написали под эту железку, причем для разнопланового оборудования - продаются, пока сильно не жалуются.

lazy
07.11.2013, 10:08
причем тут ОВЕН? ) траблы в железяке )

pavelrer
07.11.2013, 21:48
Да тож так думаю, отослал свой драйвер коллегам с описанем задачи, жду коментов.
Думаю в недельку услышу ответ, посто клиент и сервер на железки поднимаю с точных исходников
производителя, проблем еще не встречали.
Уже думаю, что в моих мозгах че-то повернулось как переключился на ОВЕН, и просто не вижу в дровишках
ошибку, а она сидит и смотрит.

sc200457
17.11.2013, 15:40
Тут видео довольно понятно про сокеты.
http://www.youtube.com/watch?v=ThVLXygHnnU

pavelrer
25.11.2013, 17:08
Тут видео довольно понятно про сокеты.
http://www.youtube.com/watch?v=ThVLXygHnnU

Спасибо, победил

pavelrer
03.12.2013, 16:13
Вот такая штука если в конфигурации задач стоит время выполнения моего сервера менее 40ms.
иногда пакеты склеиваются в один, чем меньше время , тем больше и чаще клей.
В чем может быть, ну или объясните может так и должно?

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

-------------------------------------------

Если не сложно посмотрите код.
Вот в чем штука, все работает, пакеты не теряются, но бывает что если отвалиться соединения ( пропало питание на свиче )
Не всегда оно восстанавливается.
В чем может быть ошибка.
Спасибо.


CASE step OF
0:
hSocket:=SysSockCreate(SOCKET_AF_INET,SOCKET_STREA M,SOCKET_IPPROTO_TCP);
result_Ioctl:=SysSockIoctl(hSocket, SOCKET_FIONBIO, ADR(mode) );
step:=6;
6:
IF hSocket = SOCKET_INVALID THEN
step:=0;
ELSE
step:=1;
END_IF
1:
sa.sin_family:=SOCKET_AF_INET;
sa.sin_addr:=SOCKET_INADDR_ANY;
sa.sin_port:=SysSockHtons(80);

result_Bind:=SysSockBind(hSocket,ADR(sa), SIZEOF(sa));
result_Listen:=SysSockListen(hSocket, 1);
step:=2;
2:
hSockClient:=SysSockAccept(hSocket, ADR(sa), SIZEOF(sa));
step:=5;
5:
IF hSockClient <> 16#FFFFFFFF THEN
step:=3;
ELSE
step:=2;
END_IF
3:

Size_Recv:=SysSockRecv(hSockClient, ADR(Buff_Recv), 256, 0 );

IF Size_Recv > 0 THEN
Buff_Send := Buff_Send+1;
Size_Send:=SysSockSend(hSockClient, ADR(Buff_Send), 10 + 1, 0 );
step:=2;
ELSE
Buff_Send := Buff_Send+1;
Size_Send:=SysSockSend(hSockClient, ADR(Buff_Send), 10 + 1, 0 );
step:=2;
END_IF


4:
SysSockClose(hSockClient);
SysSockClose(hSocket);
step:=0;

END_CASE

lazy
04.12.2013, 09:44
1. SysSockListen должен возвратить 0. соответственно может потребовацо несколько вызовов.
2. SysSockAccept в ПЛК не имеет смысла (по крайней мере пока) можно не вызывать вовсе.
3. у тебя SysSockRecv и SysSockSend вызываюцо в одном цикле ПЛК - это методически неграмотно. нужно разнести по циклам.
4. не совсем понял что ты передаешь. Buff_Send - простое число? дворд там или ворд? почему diBufferSize равен 10 + 1? должно быть хотя бы SIZEOF( Buff_Send ).
5. зачем после чтения/передачи снова step:=2;?
6. если связь пропала то в течении какого то времени Size_Recv или Size_Send будут равны -1.
соответственно после этого чтобы связь востановить нужно закрыть сокет и и начать со step=0. при этом обратить внимание чтобы номер нового сокета был таким же.
7. SysSockIoctl - не обязательно
8. hSocket - понятно, что такое hSockClient? откуда он взялсо и почему прием/передача именно в этот сокет?

UDP: дошло hSockClient у тебя равно hSocket поэтому и связь есть. вощем hSockClient - лишнее. так как SysSockAccept вызывать не нужно.

pavelrer
04.12.2013, 19:20
1.SysSockListen должен возвратить 0. соответственно может потребовацо несколько вызовов.
Уменя всегдп = 0. Но раз уж говорите сделаю проверку, думаю не повредит.

2.SysSockAccept в ПЛК не имеет смысла (по крайней мере пока) можно не вызывать вовсе.
А как это, нет смысла? А если у меня на diSocket сидят несколько клиентов в очереди, как
Я их разбирать буду кто есть кто?
Я вот потому и использую SysSockAccept.
( далее просто будет два сервера один для обмена, другой web )
3. у тебя SysSockRecv и SysSockSend вызываюцо в одном цикле ПЛК - это методически неграмотно. нужно разнести по циклам.
Просто по разным шагам раскидать?

6. если связь пропала то в течении какого то времени Size_Recv или Size_Send будут равны -1.
соответственно после этого чтобы связь востановить нужно закрыть сокет и и начать со step=0. при этом обратить внимание чтобы номер нового сокета был таким же.
Угу, спасибо – что-то потерял обрыв, поправил.
А что значит обратить внимание чтоб номер нового сокета был таким же после шага 0: ?

diBufferSize равен 10 + 1? – это просто так написал там у меня будет len(Buff_Send) + 1. + 1 просто 0 в конце будет.

5. зачем после чтения/передачи снова step:=2;?
Ну я думаю так, что если клент отвалился, то его надо поднять на место. Ну и думаю тут разбор клиентов по hSockClient.
Хотя у меня клиент будет всего один.
step:=2; - переход суда решила один вопрос связанный с потерей пакетов, т.е после приема в плк, в моем данном примере
отправка происходит моментам если нет приема, прост отсылает клиенту пакет-счетчик. Так вот после того как плк принял
данные, он сразу начинает отправлять, и клиент теряет первые 3-5 пакетов, если перехожу на stap:=2 то все нормуль.

у тебя SysSockRecv и SysSockSend вызываюцо в одном цикле ПЛК - это методически неграмотно. нужно разнести по циклам.

Ну может потеря была и вот по этой причине не грамотности, попробую разнести.

Спасибо.

pavelrer
05.12.2013, 12:34
Не подскажете, у кого какие скорости при обмене по tpc получаются? (плк 150)
Пакетов в секунду (ну я считаю пакет – строка 255).
Просто у меня как-то маловато получается, совсем.
8 - пакетов в одну сторону за секунду.
Цикл выполнения 30ms, меньше почему-то не получается, если меньше то происходит или склеивание пакетов,
или частые разрывы в соединении?!

Если мне надо поднять два сервера, один допустим сервер обмена порт 44444, другой web порт 80.
Как правильно это делать?
Не могу понять, если вызываю в разных 2х POU - SysSockCreate(SOCKET_AF_INET,SOCKET_STREAM,SOCKET_ IPPROTO_TCP);
Не работает ни один.

Думал, так – но не знаю правильно ли это?

0:
hSocket:=SysSockCreate(SOCKET_AF_INET,SOCKET_STREA M,SOCKET_IPPROTO_TCP);
result_Ioctl:=SysSockIoctl(hSocket, SOCKET_FIONBIO, ADR(mode) );
step:=6;
6:
IF hSocket = SOCKET_INVALID THEN
step:=0;
ELSE
step:=1;
END_IF
1:
(* Web ---------------------- *)
sa_web.sin_family:=SOCKET_AF_INET;
sa_web.sin_addr:=SOCKET_INADDR_ANY;
sa_web.sin_port:=SysSockHtons(80);
result_Bind_Web:=SysSockBind(hSocket,ADR(sa_web), SIZEOF(sa_web));
(* Web ---------------------- *)

sa.sin_family:=SOCKET_AF_INET;
sa.sin_addr:=SOCKET_INADDR_ANY;
sa.sin_port:=SysSockHtons(44444);
result_Bind:=SysSockBind(hSocket,ADR(sa), SIZEOF(sa));


result_Listen:=SysSockListen(hSocket, 1);
step:=2;
2:
hSockClient:=SysSockAccept(hSocket, ADR(sa), SIZEOF(sa));
hSockClientWeb:=SysSockAccept(hSocket, ADR(sa_web), SIZEOF(sa_web));
step:=5;
5:

IF hSockClientWeb <> 16#FFFFFFFF THEN
step:=3;
ELSE
step:=2;
END_IF


IF hSockClient <> 16#FFFFFFFF THEN
step:=3;
ELSE
step:=2;
END_IF

lazy
06.12.2013, 12:51
ты невнимательно читаешь сообщения по форуму )

в ПЛК - один сокет (допустим сервер) = одно подключение = ОДИН клиент )
поэтому SysSockAccept - полная лажа. код работает только потому что SysSockAccept возвращает номер сокета созданного SysSockCreate.
если будет два клиента нужно создавать два сокета сервера )

Чтобы создать несколько сокетов нужно SysSockCreate вызывать в разных циклах. Иначе SysSockCreate возвращает номер первого созданного сокета.

"обратить внимание" значит посмотреть в кодесисе с каким номером сокет открылся. по опыту если открывается с другим (значит прошлый не закрылся) то связь не востанавливаецо. в таком случае нужно перепрошить ПЛК на самую свежую прошивку.


ты проверяешь результат SysSockCreate в следующем цикле. это тоже методически неграмотно проверяй в том же.

Скорость в цифрах не помню. но на обработку одного запроса уходит два-три цикла ПЛК (у меня циклы от 5ти до 20ти ms)

pavelrer
06.12.2013, 18:27
Чтобы создать несколько сокетов нужно SysSockCreate вызывать в разных циклах. Иначе SysSockCreate возвращает номер первого созданного сокета.

"обратить внимание" значит посмотреть в кодесисе с каким номером сокет открылся. по опыту если открывается с другим (значит прошлый не закрылся) то связь не востанавливаецо. в таком случае нужно перепрошить ПЛК на самую свежую прошивку.

Создаю 2 POU, В менеджере задач, выставляем им время циклов (20ms и 30ms).
В каждом POU вызываю SysSockCreate, не один не работает?
Версия прошивки 2.15. Не пойму в чем дело.

Все остальное вроде вкурил.
SysSockAccept и неграмотность уберу – может 5ms выиграю.
Спасибо.

lazy
08.12.2013, 21:15
За POU не скажу, достаточно двух FB ) Сокеты открываюцо "системой". Вылоняецо первый POU затем второй. Это все один цикл ПЛК ) я канеш могу ошибацо ибо таких огородов (с несколькими POU) не горожу ) Напиши один работающий FB а дальше юзай его экземпляры )

pavelrer
09.12.2013, 16:24
Напиши один работающий FB а дальше юзай его экземпляры

Тут вот какая штука выходит, первый сервер у меня для обмена работает 30ms.
Второй веб-сервер, работает 150ms иначе просто то что летит от браузера видимо не успевает
попасть в 30ms, при 150ms веб сервер работает. Если я запихну в два FB как мне сделать разные
скорости исполнения. Одн то я сделаю допустим 30ms, а вот вторую как?
Спасибо.

pavelrer
09.12.2013, 19:08
Спасибо, разобрался, невнимательно просто делал.

pavelrer
10.12.2013, 18:55
Вроде все почистил, вроде все ненужное убрал и как-то полегши стало.
Осталось одно маленькое НО.
Все 30ms. Как не кручу если скорость меняю с 5ms до 25ms время от времени пакеты склеиваются
Когда в два, когда в четыре, а иногда и в восемь. Вижу по счетчику в пакете и длине пакета.
четко, без потерь просто склеились в один. Хотя при 5ms иногда сыплются но не сильно.
30ms – у меня выходит 10пакетов в одну сторону, я шлю строки и шибко разницы что я посылаю
пакет из 3х байт , что из 1000 не вижу – как было 10 пакетов, так и осталось.
При уменьшении скорости связь уже не рвется, поправил – ура.

Но вот скорость, хотя бы до 20ти пакетиков в секунду очень уж хотса. Так для спокойствия.
В принципе я могу со стороны клиента эти пакеты распилить и ни чего не потеряю, но
хочется разобраться почему так происходит.

Делаю так, каждый цикл

IF Buff_Send <> '' THEN
Size_Send:=SysSockSend(hSocket, ADR(Buff_Send), LEN(Buff_Send)+1, 0 );
Buff_Send:='';

Если что-то в буфере есть, то выплевываем это клиенту и чистим буфер, при следующим проходе
повторяем.
В конце пакетов что, нормальных, что склеенных мусора нет.
Не пойму LEN(Buff_Send) в таком случае то же должен удвоиться или учетвериться, а это то как
может произойти.

Вот мой пакет:
RFN ================================================== ========
00000000 52 3B 4D 4B 3B 31 39 32 3A 31 36 38 3A 30 3A 31 R;MK;192:168:0:1
00000010 31 2D 36 41 3A 37 37 3A 30 30 3A 30 30 3A 39 30 1-6A:77:00:00:90
00000020 3A 44 31 2D 30 3A 30 3A 30 3A 30 2D 32 35 35 3A :D1-0:0:0:0-255:
00000030 32 35 35 3A 32 35 35 3A 30 3B 36 34 3B 45 4F 50 255:255:0;64;EOP
00000040 00 .
RFN ================================================== ========
RFN: port=444

Так приходит склеенный:

RFN ================================================== ========
00000000 52 3B 4D 4B 3B 31 39 32 3A 31 36 38 3A 30 3A 31 R;MK;192:168:0:1
00000010 31 2D 36 41 3A 37 37 3A 30 30 3A 30 30 3A 39 30 1-6A:77:00:00:90
00000020 3A 44 31 2D 30 3A 30 3A 30 3A 30 2D 32 35 35 3A :D1-0:0:0:0-255:
00000030 32 35 35 3A 32 35 35 3A 30 3B 36 34 3B 45 4F 50 255:255:0;64;EOP
00000040 00 52 3B 4D 4B 3B 31 39 32 3A 31 36 38 3A 30 3A .R;MK;192:168:0:
00000050 31 31 2D 36 41 3A 37 37 3A 30 30 3A 30 30 3A 39 11-6A:77:00:00:9
00000060 30 3A 44 31 2D 30 3A 30 3A 30 3A 30 2D 32 35 35 0:D1-0:0:0:0-255
00000070 3A 32 35 35 3A 32 35 35 3A 30 3B 36 34 3B 45 4F :255:255:0;64;EO
00000080 50 00 P.
RFN ================================================== ========

Иногда такая склейка может повторится чере 3 пакета, а иногда через 100.

Ни кто не встречал такуб ерунду? Как такое побороть?

Спасибо

capzap
10.12.2013, 19:03
ну как бы такой ерундой ни кто не занимается. Вы бы для начала объяснили для чего Вам это нужно, так то по ТСР до 1500 байт можно за раз передать

pavelrer
10.12.2013, 19:52
Да уж, действительно ерундой.

Это я так проверяю чтоб у меня пакетики ни куда не пропали, ну соединение было постоянно.
А тут у меня вроде все на месте тока в виде непонятном.
Меня немного пугает если я повешу к этому плк 100 дискретных входов и они будут
очень часто счелкать, да и статусов дискретных выходов если много будет могу не уложиться.
А мне это надо все клиенту отдавать и от него принимать. Я понимаю что наверное надо
Все дискреты допустим входы укладывать в один пакет и или по изменению какого-либо отсылать
клиенту или в цикле работы сервера, ну или через 2,4,6 циклов работы сервера. И скорость может мне такая не понадобиться.
Обмен еще не мыслил.

Просто хочу добить, чтоб было красиво.

Да и пакетики хочется получать целые, той длинны что нужно, а не сдвойки какий-то.

Валенок
10.12.2013, 20:04
Сделайте первичную логику в ПЛК, а на ПК отсылайте результаты.
Например для дискретов - счетчики. А если дискреты - контроль, но не Di надо слать, его можно переподключить, а результат контроля

capzap
10.12.2013, 20:19
100 дискретных входов и 220 дискретных выходов это всего 40 байт, а не 1500

pavelrer
10.12.2013, 20:40
100 дискретных входов и 220 дискретных выходов это всего 40 байт, а не 1500

Это понятно

Я ж сказал, хочу понять в чем дело и все.
Не получиться так поставлю свои 30ms и усе.

Валенок
10.12.2013, 21:09
Ручной сервер на ПЛК не делал, а штатный слейв (с модбасTCP) мастеру на ПК нормально принимает+отвечает с периодом от 16мс. Если меньше - тоже какой-то мусор прилетает. Наверно не до конца докопал. Может после НГ руки дойдут.

100 дискретных входов и 220 дискретных выходов это всего 40 байт, а не 1500

А мб - это целых 250 байт ))))

capzap
10.12.2013, 21:14
вроде 320 на восемь будет 40, разве не так

Валенок
10.12.2013, 21:22
Ну я ж просто упростить код со стороны ПЛК предложил, если съём < 251 байт за раз. И раз уж все равно TCP, думаю что то же самое со временем и через syslibsocket

pavelrer
10.12.2013, 21:54
У меня уж мусора нет и с развалом пакетов разобрался, и не развал был.
Эта мая первая такая работа с плк, невнимательно делаю видимо.

Но этот клей как-то зараза достал. Всего-то осталось е-мое.

Вот еще какая мысля есть может посоветуете че.

Работа со строками, тут понял что искать клеить и.т.д операции со строками полное фуфло если она больше 255.
Увидел это тока когда веб сервер собирал, хотя потом в хелпе нашел.
А как правильно та с длинными работать, в ОЗУ?

Далее
Вот этот кусок

IF Buff_Send <> '' THEN
Size_Send:=SysSockSend(hSocket, ADR(Buff_Send), LEN(Buff_Send)+1, 0 );
Buff_Send:=''; !!!! Вот это я затираю строку, и длину хочу 0 – это я правильно делаю?

Может тут какая зараза сидит.

Может задержка нужна Buff_Send:=''; ? Может там что-то друг на дружку лезет?

Дело в том что я собирал веб сервер, первый ответ длинны№1 далее идет POST для запроса пароля, он чуть меньше
Чем №1 я там то же выполняю Buff_Send:=''; он его затирает, но когда приходит POST с паролем и логином а он заведомо
Меньше в весь прием = длинны №1 и мне сам пасворд в конце не отловить, т.к в следующим за ним мусоре может быть тег password.

Может я через жоу со строками? Не подскажите как массив из char сотворить, тут вроде char нет но как-то же вы с этим боретесь?
Вот в оскатовских бибка видел, там можно типа че - не нужное порезать, но не пробовал. Т.к не пойму почему они у меня
Ругались-ругались, а потом перестали и все три штуки прикрутились, пока че-то не совсем доверяю.

Ну и еще вопросик : плк, если не че не шлет клиенту раз в 7 секунд то рвет связь – это нормально или косяк искать?

capzap
10.12.2013, 22:15
Если хотите длиннющую строку, не делайте её из строки, а из массива байт, тем более указатель указывает на первый байт чего угодно

Валенок
10.12.2013, 22:45
Если сами принимаемые/отправляемые строки меньше 255, т.е. интервал между нулями всегда меньше 256, то для нарезки из длиннющего склеенного буфера хватит и стандарта с syslibmemом

capzap
10.12.2013, 23:07
Увлечение сислибмемом иногда приводит к глюкам проекта, но тут не это главное, зачем в плк посты слать,достаточно гета, изначально послали все вместе и логин и пароль и плк либо ответит либо страничку с фигой откроет

Валенок
10.12.2013, 23:22
Глюков с сислибмемом пока не обнаруживал. Исключение - sysmemalloc, когда с ним до середины Днепра ...
А тут сообсно только sysmemmove и нужно. С ней нереально глюкнуть.
Ну код с последовательным выделением из буфера за мин.цикл до одной строки (<255), а приемом склейки любой длины (в рамках буфера ессно) займет примерно столько же букв сколько в этом предложении.
А на плк syssockrecv присылает только строго -1 или >1 ?
А гет - это что ? :(

pavelrer
11.12.2013, 06:01
А какая разница /GET или /POST все одно просто пост в строке браузер не виден, а так…все вроде одинаково
Вроде так.
С сокетом разобрался остался только клей победить , Всем спасибо.


делайте её из строки, а из массива байт
Да наверное так и буду, че то не хочется во всякий там mem лезть.

Я, еще не очень понимаю ресурс памяти плк,
как я понял под массивы выделено 65кб, а в эти 65 кб еще какие переменные входят?
Я, прикинул, что если пакеты не будут успевать улитеть, сделать буфер круговой в 100 строк по 255 байт.
это уже скушает половину. У меня в плк отменен АКБ как факт, ретайны просто пишутся в файл,
(инструкции очень-очень редко) при загрузки этот файлик пишу в массив – тут тож 3-5кб скушает.
Веб сервер, вроде простенький но не хотса его в файлах хранить, это еще 3-5кб.
Тут так потихоньку, и полны карманы будут.
Не могу понять 65кб, это на все POU и FB или в каждом можно использовать по 65кб?, тут бы я успокоился.
А сколько максимум в массивах можно использовать?

При компиляции пишет использовано данных 1000 из 131072 байт. Это-то что? Добавляю в проект
Строковую переменную, компилирую, как была 1000 так и осталась?

А не кто не побывал Broadcast кидать в рутер и ловить с него чего полезного?

capzap
11.12.2013, 06:21
Слушайте, с такими запросамиВы бы комп использовали под веб-сервер,меньше гемора
А по поводу объема данных,есть же пример,где страницы хранятся в виде файлов и если что то нужно отправить клиенту,подгружается только то что нужно в фиксированный по размеру буффер
Чтоб при запрлсах гет ни чего небыло видно в строке,пользуйтесь аяксом

pavelrer
12.12.2013, 17:38
Был бы нужен комп – взял бы комп.
А запросов-то тут всего ничего.
Создал 7 POU d в каждом дает по 64к забрать. Главное чтоб в этом геморроя какого не оказалось!?
За аякс спасибо, че-то меня пугало изначально, но терь нет.

pavelrer
13.12.2013, 02:06
Создал 7 POU d в каждом дает по 64к забрать. Главное чтоб в этом геморроя какого не оказалось!?

Это я тут начудил. 7*64к ни как нормально не лезит - 131к max. (в офлайне красота, хоть теробайт заберай :) )
Ну зато понял, че откудо выделяется :)

pavelrer
15.03.2014, 00:20
ну как бы такой ерундой ни кто не занимается. Вы бы для начала объяснили для чего Вам это нужно, так то по ТСР до 1500 байт можно за раз передать
Вот наткнулся на этот косяк.
Web сервер на plc 150.
Обрывает пакет (собстно html странички) более 1600.
Как победить если моя html страничка больше этого размера?
Спасибо.
Смотрел пример веб сервера там index 3k и прилетает, не смог понять как там реализованно передача пакета более 1,5к..................?

Scream
18.07.2014, 15:44
Всем привет.

Создаю TCP сокет, делаю коннект и отправляю буфер, всё приходит и работает.
Если я не отправляю с плк ничего более 10 секунд, то происходит отключение.
Где этот таймаут?

Мне нужно чтобы этот плк не отваливался при простое.

Спасибо

Scream
21.07.2014, 11:23
Нет мыслей?
Все обязательно постоянно чтото шлют? или только у меня отваливается.
Еще вопрос, в библиотеке TcpUdplib в функциях tcpreceivedata, tcpsenddata и tcpserverwaitforconnect есть переменная SOCKET_FD_SET что это за переменная и где она описана?
------------------------------------------------------------------------
Нашел её описание.

Проблема не решена. Если плк подключается к серверу и не отправляет 15 секунд ничего, то происходит дисконнект, хочу чтобы он часами висел, а как только нужно сразу отправил данные.
Помогите гуру решить проблему.

capzap
21.07.2014, 11:42
точно речь о секундах, вроде не должно отваливаться, проект надо смотреть

Scream
21.07.2014, 12:45
Вот скрины
Мои изменения в библиотеке:
1) При передаче аргументов функции TcpClientOpenSocket передается порт (я удивился когда увидел что тип INT, у меня например порт нужен 54545, но не смертельно), IP в формате строки (я изменил на DINT и сам подсчитал, функция GetIPAddress у меня не работает, но она мне и не нужна), 3й аргумент я предположил что это размер кадров, поправьте если не так.

2) В функции TcpClientOpenSocket закоментил проверку SysSockConnect на FALSE, у меня она не работает.

Все изменения на скрине и полным кодом. Если нужно то и проект могу скинуть.

Работа программы:
1)x:=1 [открывается сокет и коннектится на 192.168.2.60:32320]
сервер написан на делфи, ничего не делает кроме вывода в лог сообщений о открытии, присоединении и закрытии подключения.(если нужно кину исходники или exe)
2)x:=2 [отправляется 10 байт]
сервер их принимает и всё в принципе работает

Если ничего плк не отсылает серверу в течении 15 секунд, то он отключается, сокет плк при этом не закрывается, тоесть не освобождается, только в ручную.

capzap
21.07.2014, 14:06
Не приветствовал бы использование динамических адресов, есть куча свободных портов и в формате двухбайтового слова, со строчным представлением адреса я тоже не заморачивался, третий аргумент тоже не использую, см.ниже
по проверке SysSockConnect тоже в приведенном коде


diSocket:=SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_IP);
IF diSocket <> SOCKET_INVALID THEN
SysSockIoctl(diSocket, SOCKET_FIONBIO, ADR(dint_true));
sa.sin_family:=SOCKET_AF_INET;
sa.sin_addr:=SysSockNtohl(DWORD_OF_BYTE(192,168,1, 99));
IF sa.sin_addr <> SOCKET_INADDR_NONE THEN
sa.sin_port:=SysSockNtohs(iPort);
IF SysSockConnect(diSocket, ADR(sa), SIZEOF(sa)) <0 THEN
SysSockClose(diSocket);
diSocket:=SOCKET_INVALID;
END_IF
ELSE
SysSockClose(diSocket);
diSocket:=SOCKET_INVALID;
END_IF
END_IF
TcpClientOpenSocket:=diSocket;
так должно работать


По поводу отключений, а зачем вообще держать клиента на связи длительное время, ладно бы речь шла о сервере. Получили ответ на запрос и отключились (причем корректно отключились, чтоб в процессе не напороться на проблему не закрытого сокета)

Scream
21.07.2014, 14:27
Адрессы статичны.насчет остального согласен.
Не понял где объявлена dint_true.

А идея в следующем, есть 10 фасовочных аппаратов, у каждого свой плк, все они в промышленной сети. Персонал работает за аппаратом и могут ставить тару хаотично конечно. Сокет плк коннектится при включении аппарата к серверу и присылает налитый вес продукта, тоесть всегда данные идут асинхронно и хаотично, поэтому метод опрос\ответ не очень то и подходит. Плк сам контролирует изменение значения и отправляет по своему протоколу данные, никто никого не опрашивает. Персонал может уйти на обед (1 час), перекур (15 минут), за тарой (от 2 минут до 10) и т.д в этом случае слать никому ничего не надо (простой работы). Поэтому хотелось бы чтоб плк всегда был в онлайн если включена машина и без лишнего трафика.

Как вариант вижу это раз например в 5 секунд слать данные типо "Привет, я №5 онлайн!" но это костыли помоему. Гдето ж должен быть этот таймаут или биндить надо или еще чтото не пойму(

За критику и идеи буду очень признателен!

capzap
21.07.2014, 14:40
слать приветы, это разве не трата трафика из Вашего концепта, а с другой стороны почему серверу(СКАДЕ) не знать каково состояние фасовочника в любой момент времени, http://www.owen.ru/forum/showthread.php?t=12729&p=83833&viewfull=1#post83833 на видео не могу сказать что пауза у клиента была более 10секунд, но если бы были проблемы я бы заметил, но что то не припоминаю чтоб у меня отключалось что то.

Из идей я бы предложил перейти на UDP

Scream
21.07.2014, 17:31
Если честно не понял задумку из видео.
Но сама суть то очень простая, просто ждать и не отключаться, неужели невозможно это написать?
Проверял на плк 100 и на плк 160, всё аналогично.

capzap
21.07.2014, 19:31
так тему прочитайте, у меня на одном плк и сервер и клиент, через транзит отправляю информацию и она же возвращается строчкой ниже, при тестах паузы какое набор символов написать были и побольше 30 секунд


ЗЫ
Проверял на плк 100 и на плк 160, всё аналогичнозначит проблемы в Вашем коде

Scream
22.07.2014, 11:56
Что ж Вы рассказываете?

У Вас стоит таймер, который делает переменную foo=0, а посылка данных как раз каждый цикл проверка на foo = 0, после отсылки foo опять = 1, чтобы не слать постоянно.
Так что нет у Вас никаких 30 секунд.
Если не сложно проверьте моё обоснование, просто подключитесь к серверу и ждите отключение, так ли это?
Спасибо.

capzap
23.07.2014, 17:58
сейчас в командировке, не могу проверить,но повторю соединение должно держаться

Scream
23.07.2014, 22:09
Спасибо.
Здесь видно что держится, но plcWinNT, потом если будет возможно на реальном овен плк проверить бы.

Scream
24.10.2014, 14:48
Хочу поднять тему снова.
Я ранее писал о том что при установлении связи ПЛК (socketClient) <----> ПК (socketServer), плк отключается если в течении ~15 секунд ничего не принято\отправлено.
Это действительно так, но заметил еще вот что.
Время, через которое происходит отключение зависит от времени цикла установленного в конфигураторе MinCycleLength ms...
Так у меня в ПЛК160 при:
1ms отключение через 10 сек
2ms отключение через 11,1 сек
3ms отключение через 11,1 сек
4ms отключение через 11,2 сек
5ms отключение через 13,8 сек
6ms отключение через 11,2 сек
7ms отключение через 13,0 сек
50ms отключения не долждался.

Какие у кого мысли насчет этого?

P.s. читал как то книжку, если не ошибаюсь Хортсман (java). Так вот, он пишет что сокет действительно может так себя вести и предлагает делать так как я писал в посте №65 данной темы.

vooodooo22
19.10.2016, 23:42
За POU не скажу, достаточно двух FB ) Сокеты открываюцо "системой". Вылоняецо первый POU затем второй. Это все один цикл ПЛК ) я канеш могу ошибацо ибо таких огородов (с несколькими POU) не горожу ) Напиши один работающий FB а дальше юзай его экземпляры )

Доброго времени суток

Подскажите пожалуйста, я по вышеописанному принципу создал "один работающий FB" для обмена данными по UDP:
итерация 1. Сокет открыл, посылку отправил
итерация 2. жду ответа (n := n + 1; (*счетчик итераций*) далее просто проверяем если счетчик равен заданному количеству или пакет получен, закрываем сокет)

Если я использую один экземпляр данного FB, все хорошо.

Но если экземпляров становится больше (например 2) и один экземпляр обращается к несуществующему устройству Dev1 (сокет открывается, посылка идет, но ответа нет), а другой экземпляр к существующему Dev2 (ответы приходят), то ответные пакеты от устройства Dev2 начинаются теряться, либо приходят но с очень большим запозданием.

В коде использовал функцию SysSockSelect(), в которой указывал тайм-аут 1 сек. Но даже закомментив данный кусок кода все равно получаю такую бяку =(
Пробовал в SysSockSelect() выставить тайм-аут = 0, ситуация улучшилась, количество потерянных пакетов уменьшилось, но все равно полностью от этого избавиться пока не смог.

1. Такое ощущение, что функция SysSockRecvFrom() устройства Dev1 блокирует поток на N-ое время, за которое SysSockRecvFrom() устройства Dev2 теряет ответный пакет. Возможно ли такое?

2. Есть ли у функции SysSockRecvFrom() какое-то ограничение по времени по принятию пакета?

3. Или может быть эту функцию тоже как и открытие сокета нельзя вызывать в одной итерации ПЛК (хотя в ней же указывается с какого сокета принимать)?

4. Может ли влиять на эту ситуацию тот факт, что экземпляры выше описанного FB вызываются в программе PLC_PRG друг за другом в одной итерации, т.е. получается, что сокеты этих экземпляров открываются в одной итерации?


Спасибо большое всем откликнувшимся!

Филоненко Владислав
20.10.2016, 11:23
Хочу поднять тему снова.
Я ранее писал о том что при установлении связи ПЛК (socketClient) <----> ПК (socketServer), плк отключается если в течении ~15 секунд ничего не принято\отправлено.
Это действительно так, но заметил еще вот что.
Время, через которое происходит отключение зависит от времени цикла установленного в конфигураторе MinCycleLength ms...
Так у меня в ПЛК160 при:
1ms отключение через 10 сек
2ms отключение через 11,1 сек
3ms отключение через 11,1 сек
4ms отключение через 11,2 сек
5ms отключение через 13,8 сек
6ms отключение через 11,2 сек
7ms отключение через 13,0 сек
50ms отключения не долждался.

Какие у кого мысли насчет этого?

P.s. читал как то книжку, если не ошибаюсь Хортсман (java). Так вот, он пишет что сокет действительно может так себя вести и предлагает делать так как я писал в посте №65 данной темы.

Таймаут на закрытие соединения без данных - это штатная функция стека TCP/IP. Просто у Windows это время по умолчанию - 2 часа.
Также в ПЛК это время зависит от времени цикла, это штатное поведение.

Филоненко Владислав
20.10.2016, 11:25
Доброго времени суток

Подскажите пожалуйста, я по вышеописанному принципу создал "один работающий FB" для обмена данными по UDP:
итерация 1. Сокет открыл, посылку отправил
итерация 2. жду ответа (n := n + 1; (*счетчик итераций*) далее просто проверяем если счетчик равен заданному количеству или пакет получен, закрываем сокет)

Если я использую один экземпляр данного FB, все хорошо.

Но если экземпляров становится больше (например 2) и один экземпляр обращается к несуществующему устройству Dev1 (сокет открывается, посылка идет, но ответа нет), а другой экземпляр к существующему Dev2 (ответы приходят), то ответные пакеты от устройства Dev2 начинаются теряться, либо приходят но с очень большим запозданием.

В коде использовал функцию SysSockSelect(), в которой указывал тайм-аут 1 сек. Но даже закомментив данный кусок кода все равно получаю такую бяку =(
Пробовал в SysSockSelect() выставить тайм-аут = 0, ситуация улучшилась, количество потерянных пакетов уменьшилось, но все равно полностью от этого избавиться пока не смог.

1. Такое ощущение, что функция SysSockRecvFrom() устройства Dev1 блокирует поток на N-ое время, за которое SysSockRecvFrom() устройства Dev2 теряет ответный пакет. Возможно ли такое?

2. Есть ли у функции SysSockRecvFrom() какое-то ограничение по времени по принятию пакета?

3. Или может быть эту функцию тоже как и открытие сокета нельзя вызывать в одной итерации ПЛК (хотя в ней же указывается с какого сокета принимать)?

4. Может ли влиять на эту ситуацию тот факт, что экземпляры выше описанного FB вызываются в программе PLC_PRG друг за другом в одной итерации, т.е. получается, что сокеты этих экземпляров открываются в одной итерации?


Спасибо большое всем откликнувшимся!
Select - блокирующая функция. Использовать её я не рекомендую именно из-за блокирования. Гораздо правильнее будет по очереди попробовать прочитать из сокета и проанализировать код ошибки или просто по таймауту при отсутствии данных.