реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Программирование COM под Windows, не могу справится с переполнением приемного буфера
paskal
сообщение Nov 19 2012, 16:10
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769



Проверяю UART некоторого устройства через компьютер. Программа написана на C++ билдере под ХР. Прием - передача в принципе работает. Компьютер посылает блок данных, устройство в ответ шлет свой блок, комп его принимает. Программа при этом работает исключительно в синхронном режиме: пошлет пакет, ожидает ответного пакета.

Но есть еще отдельный режим, когда устройство посылает поток байт, а компьютер ничего с ними не делает. После этого программа перестает работать. Выяснил что это происходит из за переполнения приемного буфера, но вылечить это не могу. Не помогает ни вызов ClearCommError, ни закрытие-открытие порта. Да и не может помочь, т.к. в пошаговой отладке выяснилось что переменная в которой хранился дескриптор порта (полученный вызовом CreateFile) - затирается. Т.е. я в принципе не могу работать с портом. Пробовал устранить переполнение присвоением false в переменной dcb->fAbortOnError - не помогло.
Что еще посоветуете?
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 19 2012, 16:17
Сообщение #2


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Посоветую увеличить размер буфера (можно входного и выходного сразу).

Делается это фукцией API:
SetupComm(COMhandle, InBufSize, OutBufSize);
Только, чур, нечетных размеров не задавать, и длиннее, чем 65634 тоже поостеречься (нет у меня уверенности, что третий байт не откусит).
Go to the top of the page
 
+Quote Post
paskal
сообщение Nov 19 2012, 16:42
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769



Цитата(Xenia @ Nov 19 2012, 19:17) *
Посоветую увеличить размер буфера (можно входного и выходного сразу).

Нет, не годится. Количество мусора, который может прийти неограничено. Буфер любого размера все равно когда то переполнится.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 19 2012, 16:52
Сообщение #4


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(paskal @ Nov 19 2012, 20:42) *
Нет, не годится. Количество мусора, который может прийти неограничено. Буфер любого размера все равно когда то переполнится.


Буфер (тот, который по SetupComm заводится) самоочищается на столько байт, сколько вы читаете из COM-порта.

Ну, а если вы открыли COM-порт, как файл, и погнали в него с внешнего устройства информацию, а средства оперативного чтения (хотя бы раз в секунду) не предусмотрели, то вы сами себе злобный Буратино sm.gif.

Обычно на таймер (ПК-шный) нагружают процедуру, которая периодически с каким-то постоянным периодом читает из СОМ-порта и хотя бы на диск эти данные пишет, если сама не знает, что с ними делать. Буфер не хранилка данных, а лишь средство, чтобы продержаться (не потерять данные) между их поступлением в ПК и чтением их из программы.
Go to the top of the page
 
+Quote Post
paskal
сообщение Nov 19 2012, 17:16
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769



Таймер там не нужен потому что алгоритм работы предельно простой: программа послала блок и тут же приняла ответный блок уже известной длины.
Ввести таймер можно, но это мне кажется слишком тяжеловесным решением. Надо еще следить чтоб таймер не вмешался в прием нужных данных.
Можно между посылками закрывать порт и открывать когда нужно послать очередной раз. Но это тоже много лишних действий - после очередного открытия надо настраивать таймауты, режимы через dcb. Вот если бы можно было переводить порт как бы в спячку, чтоб он временно ничего не принимал. Но как это сделать я не знаю.
И еще я не понимаю почему простое переполнение приводит к таким последствиям что забиваются переменные. Может это тоже можно как то устранить?
Go to the top of the page
 
+Quote Post
zombi
сообщение Nov 19 2012, 18:18
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



1. Попробуйте всегда перед началом работы с портом выполнить PurgeComm.
2. Не думаю что виндовский буфер может что то затирать кроме себя. biggrin.gif Неужели Вы думаете что винда может не контролировать переполнение буфера и что то там затирать? biggrin.gif
Go to the top of the page
 
+Quote Post
Xenia
сообщение Nov 19 2012, 18:20
Сообщение #7


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(paskal @ Nov 19 2012, 21:16) *
Можно между посылками закрывать порт и открывать когда нужно послать очередной раз. Но это тоже много лишних действий - после очередного открытия надо настраивать таймауты, режимы через dcb. Вот если бы можно было переводить порт как бы в спячку, чтоб он временно ничего не принимал. Но как это сделать я не знаю.
И еще я не понимаю почему простое переполнение приводит к таким последствиям что забиваются переменные. Может это тоже можно как то устранить?

Мне не понятно ваше возражение о том, что "Буфер любого размера все равно когда-то переполнится". С чего бы ему вдруг переполняться, если вы посылки регулярно забираете? Этот буфер FIFO, и переполниться он может только если посылки будут приходить, а получать вы их не будете. Если вы наотрез отказываетесь использовать SetComm для установки размера буфера, то буфер все равно будет, только по умолчанию в 16 байт. Влезает в них ваша посылка?

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


Цитата(zombi @ Nov 19 2012, 22:18) *
Неужели Вы думаете что винда может не контролировать переполнение буфера и что то там затирать? biggrin.gif

Винда не обязана заполнять всю свою память или писать на диск всю ту муру, что приходит на СОМ-порт. Она складирует "неполученные отправления" до тех пор, пока не кончится место в заказанном программой (которая тот СОМ-порт открыла) буфере. Эти данные уже не пропадут, но попадут те, которые пришли вслед за ними, и которым места в буфере нехватило.
Go to the top of the page
 
+Quote Post
zombi
сообщение Nov 19 2012, 18:50
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(Xenia @ Nov 19 2012, 22:20) *
... Эти данные уже не пропадут, но попадут те, которые пришли вслед за ними, и которым места в буфере нехватило.

Это Вы к чему???
Я с Вами полностью согласен.
Но ТС пишет :
Цитата(paskal @ Nov 19 2012, 21:16) *
И еще я не понимаю почему простое переполнение приводит к таким последствиям что забиваются переменные. Может это тоже можно как то устранить?

Т.е. ТС считает что в программе что то "забивается", "затирается" именно из за переполнения буфера.
Go to the top of the page
 
+Quote Post
paskal
сообщение Nov 19 2012, 19:08
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769



Цитата(zombi @ Nov 19 2012, 21:18) *
1. Попробуйте всегда перед началом работы с портом выполнить PurgeComm.

Не получится. После переполения теряется дескриптор, а он нужен в том числе и для PurgeComm.
Цитата(zombi @ Nov 19 2012, 21:18) *
2. Не думаю что виндовский буфер может что то затирать кроме себя. biggrin.gif Неужели Вы думаете что винда может не контролировать переполнение буфера и что то там затирать? biggrin.gif

Честно - совсем так не думал. Но это происходит и я не могу понять почему.


Цитата(Xenia @ Nov 19 2012, 21:20) *
Мне не понятно ваше возражение о том, что "Буфер любого размера все равно когда-то переполнится". С чего бы ему вдруг переполняться, если вы посылки регулярно забираете? Этот буфер FIFO, и переполниться он может только если посылки будут приходить, а получать вы их не будете.

Забираю я из буфера не регулярно. А ненужные посылки идут непрерывно.
Ситуация такая. Есть посылки которые шлет компьютер по нажатию мышкой, и получает тут же ответ. Это все работает. А можно переключить пульт в автономный режим. И в этом режиме в компьютер непрерывно шлется мусор. Компьютер в это время ничего не делает, но буфер его наполняется мусором. И количество мусора ничем не ограничено.

Цитата(Xenia @ Nov 19 2012, 21:20) *
На ваш вопрос я уже ответила (или попыталась ответить) советом увеличить размер буфера. Если вы знаете размер посылки, то сделайте размер приемного буфера раз в 10 больше,

Да хоть в 1000 раз, все равно он теоретически может переполниться, я уже сказал что такой вариант мне не подходит.
Go to the top of the page
 
+Quote Post
zombi
сообщение Nov 19 2012, 19:09
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(paskal @ Nov 19 2012, 21:55) *
После переполения теряется дескриптор

НЕ ВЕРЮ. Как такое возможно!!! Не должно такого быть!!!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 19 2012, 19:10
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (paskal @ Nov 19 2012, 20:55) *
Не получится. После переполения теряется дескриптор,
Но подумайте, что вы такое пишете? Дескриптор в винде - это указатель, которая винда дает вам при открытии прота. Вы его храните у себя, как он может потеряться? Разве что ваша программа неловким движением что-то пишет в ту ячейку, куда вы положили этот указатель.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
paskal
сообщение Nov 19 2012, 19:39
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769



Цитата(Сергей Борщ @ Nov 19 2012, 22:10) *
Но подумайте, что вы такое пишете? Дескриптор в винде - это указатель, которая винда дает вам при открытии прота. Вы его храните у себя, как он может потеряться? Разве что ваша программа неловким движением что-то пишет в ту ячейку, куда вы положили этот указатель.

Ну не знаю, просто говорю что вижу в отладчике. А я этот дескриптор не трогаю. Да и происходит это во время когда моя программа ничего не делает, но в порт летит мусор. Завтра еще перепроверю.
Ну а как бы временно приостановить прием есть варианты?
Go to the top of the page
 
+Quote Post
paskal
сообщение Nov 19 2012, 19:42
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769



дубль. сорри.
Go to the top of the page
 
+Quote Post
XVR
сообщение Nov 20 2012, 08:50
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(paskal @ Nov 19 2012, 23:39) *
Ну а как бы временно приостановить прием есть варианты?
Прием останавливается сам, как раз при переполнении буфера (при этом порт переходит в состояние ошибки). Затираться ничего нигде не должно.
Цитата
Ну не знаю, просто говорю что вижу в отладчике. А я этот дескриптор не трогаю. Да и происходит это во время когда моя программа ничего не делает, но в порт летит мусор.
Ищите ошибку у себя в программе. Скорее всего вы не обрабатываете ошибки, которые функции работы с портом будут возвращать после переполнения буфера.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Nov 20 2012, 09:39
Сообщение #15


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(zombi @ Nov 19 2012, 22:18) *
2. Не думаю что виндовский буфер может что то затирать кроме себя. biggrin.gif Неужели Вы думаете что винда может не контролировать переполнение буфера и что то там затирать? biggrin.gif

Открыли порт - на куче появился дескриптор. Задали буфер - он лег рядом. Пошли писать - вышли за пределы и затерли соседние данные.
Никто за вас не обязан отслеживать границы массивов.

Цитата(Сергей Борщ @ Nov 19 2012, 23:10) *
Дескриптор в винде - это указатель, которая винда дает вам при открытии прота. Вы его храните у себя, как он может потеряться?

У себя - это где?
А буфер где?


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 02:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01487 секунд с 7
ELECTRONIX ©2004-2016