Просмотр полной версии : TCP клиент на SysLibSockets
Добрый день. Тестирую пример TCP клиента на вышеуказанной библиотеке на ПЛК154. Интересует следующее: когда открываю соединение и клиент подключается к серверу и держит соединение несколько секунд, после соединение закрывается, если ничего не отправлять на сервер или обратно. Как держать соединение пока сервер работает и как ловить ошибки отправки по сокету в Codesys?
Филоненко Владислав
18.09.2015, 13:11
Это стандартное поведение сокета. если нет данных - через таймаут сокет закрывается.
Есть функция получения кода последней ошибки.
Функция SysSockSetOption(socket, SOCKET_IPPROTO_TCP, SOCKET_TCP_NODELAY, ADR(sa), SIZEOF(sa)); меняет таймаут?
Сформулирую вопрос иначе: могу ли я открыть соединение и, к примеру, один раз в 20 секунд что-то отправлять с клиента не разрывая соединение?
Филоненко Владислав
19.09.2015, 13:50
Стек IP в 1хх достаточно сильно урезан и опции сокетов не поддерживаются.
Значит стандартными средствами я не смогу организовать свой протокол обмена? Если какие-то пути решения задачи? Кто-нибудь сталкивался с этим?
Добрый день. Тестирую пример TCP клиента на вышеуказанной библиотеке на ПЛК154. Интересует следующее: когда открываю соединение и клиент подключается к серверу и держит соединение несколько секунд, после соединение закрывается, если ничего не отправлять на сервер или обратно. Как держать соединение пока сервер работает и как ловить ошибки отправки по сокету в Codesys?
Мы используем пакеты "Heartbeat" раз в секунду для контроля и поддержания соединения во время отсутствия активного обмена. Функция SysSockSend возвращает количество успешно переданных байт => можно ловить ошибки отправки.
Мы используем пакеты "Heartbeat" раз в секунду для контроля и поддержания соединения во время отсутствия активного обмена. Функция SysSockSend возвращает количество успешно переданных байт => можно ловить ошибки отправки.
Идея Ваша решает эту проблему и, видимо, без "пинговых" пакетов мне не обойтись. Попробую ловить ошибки отправки как Вы сказали.
И очень смущает, что SysSockConnect() не возвращает TRUE, хотя работает...
И очень смущает, что SysSockConnect() не возвращает TRUE, хотя работает...У Овна в ПЛК 1хх что в SysLibSockets, что в SysLibCom бардак в аргументах и возвращаемых значениях.
Подскажите еще момент, передаю строку командой SysSockSend(), на серверу получаю строку с "мусором" , аналогично с сервера приходят данные с ненужными символами.
Филоненко Владислав
22.09.2015, 16:50
размер точно указываете или как strlen()?
Указываю как SIZEOF(mystring).
Филоненко Владислав
22.09.2015, 18:22
вот вот, а в строке данных меньше чем её размер. Надо явно указывать сколько байт посылать.
KeepAlive называется чтобы сокет не умирал. Я в этих пакетах заодно данные передаю.
вот вот, а в строке данных меньше чем её размер. Надо явно указывать сколько байт посылать.
Исправил, помогло, спасибо за подсказку.
Подскажите момент: одновременно по таймеру выполняю две функции SysSockSend(), сокет создан в неблокирующем режиме SysSockIoctl(socket, SOCKET_FIONBIO, 1), но результат выполнения второй функции возвращает -1. Сделал это ради эксперимента, так как возможна одновременная отправка данных по сокету, а успех отправки очень важен.
Филоненко Владислав
30.09.2015, 10:46
А вставить паузу?
Я рассматриваю вариант если совпадет отправка двух или более пакетов данных по сокету, то я не смогу избежать потери информации. Или неблокирующие сокеты не поддерживаются?
Я рассматриваю вариант если совпадет отправка двух или более пакетов данных по сокету, то я не смогу избежать потери информации. Или неблокирующие сокеты не поддерживаются?
Если я правильно Вас понял, Вы пытаетесь вызвать дважды и более функцию SysSockSend за один цикл ПЛК. Я так не пробовал, но у меня, сформированные в течении цикла ПЛК пакеты складываются в специальный буфер-накопитель. Затем, в конце цикла я формирую буфер данных для отправки по сети в виде "склейки" пакетов из буфера-накопителя и передаю его с помощью SysSockSend, далее, убедившись, что весь буфер передан корректно (здесь я учитываю, что на это может уйти не один цикл ПЛК) , приступаю к формированию и передаче следующей склейки. Процесс накопления буфера сообщений (события объекта) и процесс передачи этих сообщений в сеть происходят асинхронно. Это конечно для Stream-сокета.
Если я правильно Вас понял, Вы пытаетесь вызвать дважды и более функцию SysSockSend за один цикл ПЛК.
Да, вы правильно поняли. С сокетами раньше работал, но не в кодесис, вызывал функции отправки последовательно, видимо была задержка и все отправлялось, отправки склеивались. Создал, как Вы сказали, "буфер", приходится складывать в него байтовые массивы, по другому решения задачи не вижу. Да и интервал выполнения установил 100мс, реже сокет не справляется с отправкой...
Да, вы правильно поняли. С сокетами раньше работал, но не в кодесис, вызывал функции отправки последовательно, видимо была задержка и все отправлялось, отправки склеивались. Создал, как Вы сказали, "буфер", приходится складывать в него байтовые массивы, по другому решения задачи не вижу. Да и интервал выполнения установил 100мс, реже сокет не справляется с отправкой...
наверное чаще?
наверное чаще?
Да, перепутал, не чаще. Надеюсь, что на правильном пути.
Да отправляется чаще .Просто не получилось
Да отправляется чаще .Просто не получилось
Что не получилось? Отправить не получилось? Или что имеете ввиду? Если есть что подсказать, то подскажите явно, а не воду пишите, уже несколько дней одно и тоже.
Друзья, может подскажете, как вы справлялись с сокетами, если, конечно, это для вас не секретная информация. Какое время цикла ставите, чтение\запись делаете в одном цикле, после каждой транзакции закрываете сокеты или это зависит от ПЛК? На ПЛК154 получается читать и писать в одном цикле, если SysSockCreate() возвращает 2, если 1, то читает сокет через раз, как будто сокет создался в блокирующем режиме, хотя это не так.
Какое время цикла ставите
У меня на ПЛК 110 new и ПЛК 100 МинВЦ = 0 и прекрасно и максимально быстро работает.
чтение\запись делаете в одном цикле,
В разных.
транзакции закрываете сокеты или это зависит от ПЛК?
При работе с HTTP закрываю сокет после каждой транзакции. С собственным протоколом работаю при постоянно открытом соединении.
На ПЛК154 получается читать и писать в одном цикле, если SysSockCreate() возвращает 2, если 1, то читает сокет через раз, как будто сокет создался в блокирующем режиме, хотя это не так.
Я думаю что не стоит писать и читать в одном цикле. По сокетам есть очень полезное видео (http://www.youtube.com/watch?v=ThVLXygHnnU), правда для CDS V3, но суть одна.
Сокеты не закрываю, точнее, закрываю если сокет "сервер" и к нему нет обращений какое то время (так определяю обрыв связи) чтобы в следующем цикле открыть снова. Клиенты бомбят без остановки но за цикл либо пишу либо читаю, причем если сокетов открыто много то читаю/пишу только одним сокетом, на следующем цикле другим итд. Если прием/передача проходят с ошибкой клиента закрываю чтобы открыть в следующем цикле.
С серверами сложнее. В одном цикле перебираю все фунцией чтения, если с какого есть данные(запрос) - перебор прекращаю на следующем цикле если нужно ответить отвечаю и(или) продолжаю перебор оставшихся сокетов. И так по кругу.
вощемто работает )
Спасибо за ответы! Разделил чтение\отправку, чередую в цикле. Проблема только в том, что не всегда могу получить данные, повторюсь, если если SysSockCreate() возвращает 1, если 2, то сколько бы я с сервера ни отправлял, все доходит...
Есть у меня подозрение... )
Насчет дискрипторов... У меня сокеты открываюцо с дискрипторами 1,2,3...15. Первый всегда создается с дискриптором 1. (если у вас первый с двойкой смотрите код внимательнее возможно их открываецо два и отсюда все траблы)
открываем:
IF m_dnSocket = SOCKET_INVALID THEN
m_dnSocket := SysSockCreate( ... );
END_IF
А вот с закрытием сложнее...
o_dnRes := BOOL_TO_INT( SysSockClose ( m_dnSocket ) );
для 110-го:
IF o_dnRes = 0 THEN
m_dnSocket := SOCKET_INVALID;
END_IF
причем в какой-то прошивке SysSockClose возвращал правильное значение но реально сокет не закрывался. (значит следующий отрывался с дискриптором на еденичку больше)
для 100-го:
IF o_dnRes = 1 THEN
m_dnSocket := SOCKET_INVALID;
END_IF
по моему как то так. кто сможет опровергните )
У меня открывается или с дескриптором 1 или 2, других пока не наблюдал, проверю вариант с незакрытием сокета. Просто, по логике вещей, если у меня открыто два сокета, то траблов как раз таки нет...
Филоненко Владислав
09.10.2015, 08:38
Итак, при запуске должен открываться сокет с handle=1, 0-й занят средой CoDeSys.
Если при открытии 1 сокета handle=2 - что-то тут не так.
Учтите, что listen->accept позвращает тот-же handle, т.е. как в винде нельзя поступать - открыть сокет, поставить в listen и плодить сокеты по приходящим соединениям.
1 сокет - 1 и только 1 соединение.
Итак, при запуске должен открываться сокет с handle=1, 0-й занят средой CoDeSys.
Если при открытии 1 сокета handle=2 - что-то тут не так.
Учтите, что listen->accept позвращает тот-же handle, т.е. как в винде нельзя поступать - открыть сокет, поставить в listen и плодить сокеты по приходящим соединениям.
1 сокет - 1 и только 1 соединение.
Насколько я помню, вроде плк 160, открывает с 11 дескриптора и до 16. Как тут тогда быть?
Беда, конечно, что каждый ПЛК ведет себя по-разному, а под рукой нет другого, чтобы проверить...
Беда, конечно, что каждый ПЛК ведет себя по-разному, а под рукой нет другого, чтобы проверить...
так если Вы в самом начале например открыли сокет и не продумали на тот момент о закрытии, он так и будет постоянно занят пока не произведете сброс плк, а открываться будет уже только следующий
так что ведут себя по разному это от программиста тоже зависит
это от программиста тоже зависит
Замечание ваше справедливо, себя не оправдываю, действительно мало опыта. Цель всех моих вопрос понять, где мои ошибки, а где поведение ПЛК.
Почему сокет открывается со 2-го десткриптора разобрался, но вот почему сокет читается "через раз" с дескриптором 1 так и не понял.
Филоненко Владислав
09.10.2015, 13:56
Программу то приведите, чего мы тут гадаем. На ПЛК100 мы даже WEB-сервер делали многопользовательский с визуализацией и графиками. Так что сокеты рабочие, но есть нюансы.
Программу то приведите, чего мы тут гадаем. На ПЛК100 мы даже WEB-сервер делали многопользовательский с визуализацией и графиками. Так что сокеты рабочие, но есть нюансы.
Вот, собственно, ФБ и пару функций, которыми пользуюсь, ФБ многим знаком, из оскатовской библиотеки.
20344
Эммм... что то у вас с переходом из step:=0;в step:=1; зачем прыгать туда-сюда из цикла в цикл? Принимайте (то есть будте в step:=1) пока не примите или не выйдет таймаут. Ну и с передачей собственно так же )
Эммм... что то у вас с переходом из step:=0;в step:=1; зачем прыгать туда-сюда из цикла в цикл? Принимайте (то есть будте в step:=1) пока не примите или не выйдет таймаут. Ну и с передачей собственно так же )
Суть в том, что не всегда получается прочитать то, что отправил с сервера. Пробовал оставить в цикле только чтение, результат тот же.
и все таки: передаем - передали? да - принимаем - приняли? да - передаем. инициатором обмена должен быть клиент. сервак "слушает и отвечает" (это я к тому что "оставил в цикле только чтение" )
попробуйте вместо TcpReceiveData result:= SysSockRecv( diSocket, ADR(byBuffer[0]), 100,0);
у вас "сервак" шлет данные с какой периодичностью? может сервак передает а сокет закрылся по ready и(или) errcheck?
у вас "сервак" шлет данные с какой периодичностью? может сервак передает а сокет закрылся по ready и(или) errcheck?
Сервер не отвечает на посылки, пока такой алгоритм, НО я могу с сервера в произвольный момент времени отправить данные, на которые должен отреагировать клиент, если они не доходят с первого раза, то придется "долбить" клиента, чего не совсем хочется.
И еще, пока я буду ждать от сервера ответа(который может и не придти), как в нынешней ситуации, то у меня сокет по таймауту закрывается, безысходность какая-то...
ну дык вот )
у вас сокет принимает 5 секунд и закрываецо. а вы шлете ) оставьте только прием. уберите ready и errcheck и проверьте )
В том примере, что я отправил, пусть он не совсем правильный, по идее-то, прием должен работать. Закрываться сокет стал, когда сделал по вашему совету, отправил и читаю)) я не шлю с сервера когда клиент отключен.
уберать ready и errcheck нужно не насовсем а временно чтобы проверить )
Филоненко Владислав
11.10.2015, 13:04
Вот пример сервера. Делайте по аналогии.
Вот пример сервера. Делайте по аналогии.
Собственно, ФБ, которым пользуюсь, не хуже, хотя речь идет о клиенте. В Вашем примере в одном цикле и запись, и чтение, или я ошибаюсь?
Филоненко Владислав
12.10.2015, 16:09
Хуже, лучше. Главное- хвост! (т.е. работает)
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot