|
Уроки из ошибки
|
|||
---|---|---|---|
#18+
Нашел сегодня причину ошибки и исправил. Наверное можно сказать, что среди причин ошибки было: - неправильное наследование, не идеальное, скажем так) - невнимательность - скопипастил и не посмотрел, - особенности чтения из сокета по протоколу UDP. В общем есть обмен с одним устройством. Раньше его подключали за преобразователем портов, так что к преобразователю подключались по TCP-IP, а от того шло по RS-232. Для програмы - всё равно, что просто по TCP-IP. Потом к этому устройству стали подключаться напрямую по UDP. В принципе почти всё одно и то же, есть несколько отличий. Ну, при подключении создаем сокет для UDP например. Вместо Код: Delphi 1.
Код: Delphi 1.
В общем я написал класс, реализующий обмен с устройством по UDP как наследника класса, который обменивался данными по TCP. У них есть предок с самыми общими методами, некоторыми - абстрактными. Но от этого предка есть наследник и могут быть другие и для железок других производителей. А тут надо было бы наверное сделать ещё промежуточный класс для этой конкретной железки со всеми общими методами, а от него уже унаследовать один для TCP, один для UDP. Я сделал, как меньше труда :) В принципе это задачи решило, дальше иерархия не планируется. Но вот в другой программе тоже нужен был такой обмен, скопипастил один старый вариант. А там в одном из методов, переписанных (override), сначала вызывается метод предка (inherited). А потом уже обмен по UDP. НО! не надо было вызывать метод предка, надо было бы вызвать метод предка предка (такую манипуляцию Паскаль напрямую вроде не позволяет), чтобы зачистить кое-какие структуры, или впрямую (как я сейчас сделал) очистить их. В более новой версии основной программы этой фигни нет, а тут она была. Получилось, что во-первых два раза запрос и чтение ответа делалось. Но что более важно, из-за чего ошибка была. В TCP протокол обеспечивает доставку пакета, причем, если не ошибаюсь, может его разбить, доставить по частям. И читать из сокета мы можем кусочками, по сколько хотим. Соответственно, там читался сначала заголовок пакета, в котором указана общая длина данных, а потом читалось остальное - нужное количество байт. А при UDP такого делать нельзя. В UDP приходит датаграмма целиком и её надо читать целиком. В документации на функцию recv написано: Цитата [игнорируется] Для сокетов без подключения (тип SOCK_DGRAM или других сокетов, ориентированных на сообщения), данные извлекаются из первой датаграммы (сообщения) из адреса назначения, указанного функцией connect . Если датаграмма или сообщение больше указанного буфера, буфер заполняется первой частью датаграммы, а recv создает ошибку WSAEMSGSIZE. Для ненадежных протоколов (например, UDP) лишние данные теряются; Вот. ... |
|||
s62:
Пользователь запросил модераторские права на тему.
Изменено: 17.10.2023, 22:58 - s62
Нравится:
Не нравится:
|
|||
17.10.2023, 22:55 |
|
Уроки из ошибки
|
|||
---|---|---|---|
#18+
Ну, увидел потом это ненужное там inherited. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.10.2023, 23:50 |
|
Уроки из ошибки
|
|||
---|---|---|---|
#18+
Пользователь назначен модератором темы: s62. ... |
|||
Горбатый ёж:
Пользователь назначен модератором темы: s62.
Нравится:
Не нравится:
|
|||
18.10.2023, 00:49 |
|
Уроки из ошибки
|
|
---|---|
#18+
У меня недавно из подобного было. Ошибка оказалась, что я когда создавал TObjectDictionary указал что он владеет объектами, то есть сам будет их освобождать. А потом где-то в коде еще напрямую освободил какой-то из элементов. Ну подобное. имею в виду что сразу не поймешь из-за чего ошибка. ... |
|
:
|
|
19.10.2023, 11:02 |
|
|
start [/forum/topic.php?fid=16&msg=578340&tid=13195]: |
0ms |
get settings: |
20ms |
get forum list: |
8ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
30ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
401ms |
get tp. blocked users: |
2ms |
others: | 22ms |
total: | 499ms |
0 / 0 |