powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Языки программирования семейства Pascal [закрыт для гостей] / Уроки из ошибки
Модераторы: s62
6 сообщений из 6, страница 1 из 1
Уроки из ошибки
    #576792
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Нашел сегодня причину ошибки и исправил. Наверное можно сказать, что среди причин ошибки было:
- неправильное наследование, не идеальное, скажем так)
- невнимательность - скопипастил и не посмотрел,
- особенности чтения из сокета по протоколу UDP.

В общем есть обмен с одним устройством. Раньше его подключали за преобразователем портов, так что к преобразователю подключались по TCP-IP, а от того шло по RS-232. Для програмы - всё равно, что просто по TCP-IP. Потом к этому устройству стали подключаться напрямую по UDP. В принципе почти всё одно и то же, есть несколько отличий. Ну, при подключении создаем сокет для UDP например.
Вместо
Код: Delphi
1.
FClientSocket := Socket(AF_Inet, SOCK_STREAM, 0);
вызываем
Код: Delphi
1.
FClientSocket := Socket(AF_Inet, SOCK_DGRAM, 0);
И в первом случае, не прервалось ли подключение, можно проверить просто - открыт ли сокет. А во втором случае, в UDP ведь нет понятия подключения, так что надо как-то проверять на уровне приложения. Например если сколько-то подряд раз не получили ответ от устройства, можно считать, что связь нарушена.

В общем я написал класс, реализующий обмен с устройством по UDP как наследника класса, который обменивался данными по TCP. У них есть предок с самыми общими методами, некоторыми - абстрактными. Но от этого предка есть наследник и могут быть другие и для железок других производителей. А тут надо было бы наверное сделать ещё промежуточный класс для этой конкретной железки со всеми общими методами, а от него уже унаследовать один для TCP, один для UDP. Я сделал, как меньше труда :) В принципе это задачи решило, дальше иерархия не планируется.
Но вот в другой программе тоже нужен был такой обмен, скопипастил один старый вариант. А там в одном из методов, переписанных (override), сначала вызывается метод предка (inherited). А потом уже обмен по UDP. НО! не надо было вызывать метод предка, надо было бы вызвать метод предка предка (такую манипуляцию Паскаль напрямую вроде не позволяет), чтобы зачистить кое-какие структуры, или впрямую (как я сейчас сделал) очистить их. В более новой версии основной программы этой фигни нет, а тут она была. Получилось, что во-первых два раза запрос и чтение ответа делалось.
Но что более важно, из-за чего ошибка была. В TCP протокол обеспечивает доставку пакета, причем, если не ошибаюсь, может его разбить, доставить по частям. И читать из сокета мы можем кусочками, по сколько хотим. Соответственно, там читался сначала заголовок пакета, в котором указана общая длина данных, а потом читалось остальное - нужное количество байт.
А при UDP такого делать нельзя. В UDP приходит датаграмма целиком и её надо читать целиком. В документации на функцию recv написано:
Цитата 
[игнорируется]
Для сокетов без подключения (тип SOCK_DGRAM или других сокетов, ориентированных на сообщения), данные извлекаются из первой датаграммы (сообщения) из адреса назначения, указанного функцией connect .

Если датаграмма или сообщение больше указанного буфера, буфер заполняется первой частью датаграммы, а recv создает ошибку WSAEMSGSIZE. Для ненадежных протоколов (например, UDP) лишние данные теряются;
Соответственно, когда у меня для UDP сокета вызывался метод его TCP-предка, вот эту ошибку я и получал. Убрал inherited, добавил код очистки структур и всё заработало, как надо. Спектр стал нормально сниматься. Формат пакетов известен, в том числе длина, так что можно сразу пытаться читать весь пакет.
Вот.
...
s62:
Пользователь запросил модераторские права на тему.
Изменено: 17.10.2023, 22:58 - s62
Рейтинг: 0 / 0
Уроки из ошибки
    #576798
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
s62 [игнорируется] 

А у нас в офисе, когда есть собранный макет, бывает по-разному собран - или датчик подключен через преобразователь портов, или напрямую по UDP. Я когда эту штуку писал, было как раз собрано в первом варианте. Я потестил, всё вроде работает ок. А на фабрике наш сотрудник начал использовать - не работает (там - второй вариант подключения). Я тоже посмотрел, да, прекращается измерение, непонятно почему. Ну, не катастрофично, т.к. именно это долго делали в другой программе, и так и тут продолжилось. Хорошо, что на днях появился программный эмулятор железки. Запустил с ним в офисе и в отладчике Delphi увидел, что в одной команде непонятно почему вдруг работает функция от TCP. Ну, увидел потом это ненужное там inherited.
...
Изменено: 17.10.2023, 23:20 - s62
Рейтинг: 1 / 0
Нравится: Неуловимый Джо
Уроки из ошибки
    #576810
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
s62 [игнорируется] 
Хм, может я нарушаю соглашение о неразглашении, что написал вот это на форуме... Ладно, уже не удалить, вроде особо чувствительной информации и тайн тут не было.
...
Изменено: 17.10.2023, 23:29 - s62
Рейтинг: 0 / 0
Уроки из ошибки
    #576819
Неуловимый Джо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[игнорирует гостей]
s62  17.10.2023, 23:16
[игнорируется]
Ну, увидел потом это ненужное там inherited.
такие мелочи трудно отлавливать конечно.
...
Рейтинг: 0 / 0
Уроки из ошибки
    #576885
Горбатый ёж
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Пользователь назначен модератором темы: s62.
...
Горбатый ёж:
Пользователь назначен модератором темы: s62.
Рейтинг: 0 / 0
Уроки из ошибки
    #578340
Неуловимый Джо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[игнорирует гостей]
У меня недавно из подобного было.
Ошибка оказалась, что я когда создавал TObjectDictionary указал что он владеет объектами, то есть сам будет их освобождать.
А потом где-то в коде еще напрямую освободил какой-то из элементов.

Ну подобное. имею в виду что сразу не поймешь из-за чего ошибка.
...
Рейтинг: 1 / 0
Нравится: s62
6 сообщений из 6, страница 1 из 1
Форумы / Языки программирования семейства Pascal [закрыт для гостей] / Уроки из ошибки
Модераторы: s62
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]