|
Программирование COM под Windows, не могу справится с переполнением приемного буфера |
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 23)
|
Nov 19 2012, 16:42
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(Xenia @ Nov 19 2012, 19:17)  Посоветую увеличить размер буфера (можно входного и выходного сразу). Нет, не годится. Количество мусора, который может прийти неограничено. Буфер любого размера все равно когда то переполнится.
|
|
|
|
|
Nov 19 2012, 16:52
|

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

|
Цитата(paskal @ Nov 19 2012, 20:42)  Нет, не годится. Количество мусора, который может прийти неограничено. Буфер любого размера все равно когда то переполнится. Буфер (тот, который по SetupComm заводится) самоочищается на столько байт, сколько вы читаете из COM-порта. Ну, а если вы открыли COM-порт, как файл, и погнали в него с внешнего устройства информацию, а средства оперативного чтения (хотя бы раз в секунду) не предусмотрели, то вы сами себе злобный Буратино  . Обычно на таймер (ПК-шный) нагружают процедуру, которая периодически с каким-то постоянным периодом читает из СОМ-порта и хотя бы на диск эти данные пишет, если сама не знает, что с ними делать. Буфер не хранилка данных, а лишь средство, чтобы продержаться (не потерять данные) между их поступлением в ПК и чтением их из программы.
|
|
|
|
|
Nov 19 2012, 18:20
|

Гуру
     
Группа: Модератор 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)  Неужели Вы думаете что винда может не контролировать переполнение буфера и что то там затирать?  Винда не обязана заполнять всю свою память или писать на диск всю ту муру, что приходит на СОМ-порт. Она складирует "неполученные отправления" до тех пор, пока не кончится место в заказанном программой (которая тот СОМ-порт открыла) буфере. Эти данные уже не пропадут, но попадут те, которые пришли вслед за ними, и которым места в буфере нехватило.
|
|
|
|
|
Nov 19 2012, 18:50
|

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

|
Цитата(Xenia @ Nov 19 2012, 22:20)  ... Эти данные уже не пропадут, но попадут те, которые пришли вслед за ними, и которым места в буфере нехватило. Это Вы к чему??? Я с Вами полностью согласен. Но ТС пишет : Цитата(paskal @ Nov 19 2012, 21:16)  И еще я не понимаю почему простое переполнение приводит к таким последствиям что забиваются переменные. Может это тоже можно как то устранить? Т.е. ТС считает что в программе что то "забивается", "затирается" именно из за переполнения буфера.
|
|
|
|
|
Nov 19 2012, 19:08
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(zombi @ Nov 19 2012, 21:18)  1. Попробуйте всегда перед началом работы с портом выполнить PurgeComm. Не получится. После переполения теряется дескриптор, а он нужен в том числе и для PurgeComm. Цитата(zombi @ Nov 19 2012, 21:18)  2. Не думаю что виндовский буфер может что то затирать кроме себя.  Неужели Вы думаете что винда может не контролировать переполнение буфера и что то там затирать?  Честно - совсем так не думал. Но это происходит и я не могу понять почему. Цитата(Xenia @ Nov 19 2012, 21:20)  Мне не понятно ваше возражение о том, что "Буфер любого размера все равно когда-то переполнится". С чего бы ему вдруг переполняться, если вы посылки регулярно забираете? Этот буфер FIFO, и переполниться он может только если посылки будут приходить, а получать вы их не будете. Забираю я из буфера не регулярно. А ненужные посылки идут непрерывно. Ситуация такая. Есть посылки которые шлет компьютер по нажатию мышкой, и получает тут же ответ. Это все работает. А можно переключить пульт в автономный режим. И в этом режиме в компьютер непрерывно шлется мусор. Компьютер в это время ничего не делает, но буфер его наполняется мусором. И количество мусора ничем не ограничено. Цитата(Xenia @ Nov 19 2012, 21:20)  На ваш вопрос я уже ответила (или попыталась ответить) советом увеличить размер буфера. Если вы знаете размер посылки, то сделайте размер приемного буфера раз в 10 больше, Да хоть в 1000 раз, все равно он теоретически может переполниться, я уже сказал что такой вариант мне не подходит.
|
|
|
|
|
Nov 19 2012, 19:39
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(Сергей Борщ @ Nov 19 2012, 22:10)  Но подумайте, что вы такое пишете? Дескриптор в винде - это указатель, которая винда дает вам при открытии прота. Вы его храните у себя, как он может потеряться? Разве что ваша программа неловким движением что-то пишет в ту ячейку, куда вы положили этот указатель. Ну не знаю, просто говорю что вижу в отладчике. А я этот дескриптор не трогаю. Да и происходит это во время когда моя программа ничего не делает, но в порт летит мусор. Завтра еще перепроверю. Ну а как бы временно приостановить прием есть варианты?
|
|
|
|
|
Nov 20 2012, 08:50
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(paskal @ Nov 19 2012, 23:39)  Ну а как бы временно приостановить прием есть варианты? Прием останавливается сам, как раз при переполнении буфера (при этом порт переходит в состояние ошибки). Затираться ничего нигде не должно. Цитата Ну не знаю, просто говорю что вижу в отладчике. А я этот дескриптор не трогаю. Да и происходит это во время когда моя программа ничего не делает, но в порт летит мусор. Ищите ошибку у себя в программе. Скорее всего вы не обрабатываете ошибки, которые функции работы с портом будут возвращать после переполнения буфера.
|
|
|
|
|
Nov 20 2012, 09:39
|

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

|
Цитата(zombi @ Nov 19 2012, 22:18)  2. Не думаю что виндовский буфер может что то затирать кроме себя.  Неужели Вы думаете что винда может не контролировать переполнение буфера и что то там затирать?  Открыли порт - на куче появился дескриптор. Задали буфер - он лег рядом. Пошли писать - вышли за пределы и затерли соседние данные. Никто за вас не обязан отслеживать границы массивов. Цитата(Сергей Борщ @ Nov 19 2012, 23:10)  Дескриптор в винде - это указатель, которая винда дает вам при открытии прота. Вы его храните у себя, как он может потеряться? У себя - это где? А буфер где?
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Nov 20 2012, 11:23
|
Профессионал
    
Группа: Свой
Сообщений: 1 526
Регистрация: 8-04-05
Пользователь №: 3 960

|
Цитата(paskal @ Nov 19 2012, 20:10)  что переменная в которой хранился дескриптор порта (полученный вызовом CreateFile) - затирается. Не затирается, а Вы его затираете некорректной работой с памятью, указателями итп. В С и даже в С++ система особенно не отслеживает выходы за границы массивов, выделенной области памяти для объектов, адресуемых указателями итп. Ищите у себя где Вы затираете переменную. Цитата(ARV @ Nov 20 2012, 15:19)  что не так в моем рассказе? Если устройство использует аппаратные сигналы DTR и/или RTS для разрешения работы, то при закрывании порта эти сигналы сбросятся и устройство ничего выдавать не будет. Так, кстати поступают телефонные модемы по умолчанию.
|
|
|
|
|
Nov 20 2012, 11:53
|

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

|
Цитата(MrYuran @ Nov 20 2012, 12:39)  Открыли порт - на куче появился дескриптор. Задали буфер - он лег рядом. Пошли писать - вышли за пределы и затерли соседние данные. Никто за вас не обязан отслеживать границы массивов. Я в шоке.Где TC пишет о своём буфере??? Речь идёт о стандарном виндовском. Цитата(dac @ Nov 20 2012, 13:36)  ТС походу объявил в проге массив, и считывает в него то что приходит с порта. и не проверяет размер, соответсвенно если пришло больше чем размер массива - пишет дальше  Цитата(paskal @ Nov 19 2012, 19:10)  ... Но есть еще отдельный режим, когда устройство посылает поток байт, а компьютер ничего с ними не делает...
|
|
|
|
|
Nov 20 2012, 12:20
|

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

|
Цитата(ARV @ Nov 20 2012, 15:19)  я конечно извиняюсь... но нафига вообще открывать порт, если из него не берутся данные? перешла программа в "автономный" режим - закрывать порт, и точка. все, что туда придет, будет сброшено аппаратно, ничего нигде затираться не будет. потребуется снова войти в режим "связи" - заново открывается порт, очищается его буфер (было сказано, как) и работа начинается снова...
что не так в моем рассказе? А вот что не так  . Бывают конструкции внешних устройств, которые питаются за счет сигнальных линий СОМ-порта (т.к., в отличие от USB, питание на этот разъем не подается). К такому решению располагает уменьшение энергопотребления большинства МК (им такой мощности для питания достаточно), но отвращает, что СОМ-порт постепенно выходит из моды, исчезая из стандартных устройств ПК. Часто потупают так - отказываются от хэндшейкинга, а освободившиеся линии DTR и RTS используют для питания. При этом напряжение на них уставливают в "противофазе", чтобы получить побольше разность потенциалов, и тогда из нее можно получить стабилизированное 5 вольт. Закрытие СОМ-порта приведет к тому, что выставленные уровни DTR и RTS изменятся, т.к. закрытый СОМ-порт не держит своих прежних установок. А питание внешнего устройства по многим причинам прекращать бывает нежелательно. Особенно в тех случаях, когда оно работает в ждущем режиме - не постоянно посылки гонит, а лишь в случае наступления того или иного события. Вот и было бы заманчиво установить такой режим (перепрограммирование СОМ-порта без его закрытия), чтобы (временно) отказаться от приема сообщений, но сам СОМ-порт не закрывать, чтобы сохранить уровни DTR и RTS. Всевозможные идеи (а таких можно выдвинуть много) о том, как можно организовать альтернативное питание, не взирая на полярность DTR и RTS, можете оставить при себе. Сейчас же интересует только одна вещь - возможно это сделать программным путем или невозможно. И выяснить этот вопрос хотелось бы раньше, чем брать в руки паяльник и курочить внешнее устройство.
|
|
|
|
|
Nov 20 2012, 12:32
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(Xenia @ Nov 20 2012, 16:20)  А вот что не так  . Бывают конструкции ... Xenia, бывает, что и корова летает... при себе можно вообще оставить все попытки подсказать топикстартеру методы решения его проблемы, ограничившись просто советом найти и исправить ошибку в программе - ведь это очевидно все, не так ли? кстати, топикстартер и просил "временно приостановить прием" - что может быть лучшепроще закрытия порта для этого?!
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Nov 20 2012, 14:52
|

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

|
Цитата(ARV @ Nov 20 2012, 16:32)  Xenia, бывает, что и корова летает... при себе можно вообще оставить все попытки подсказать топикстартеру методы решения его проблемы, ограничившись просто советом найти и исправить ошибку в программе - ведь это очевидно все, не так ли? кстати, топикстартер и просил "временно приостановить прием" - что может быть лучшепроще закрытия порта для этого?! Вы невнимательно читали его просьбу, а потому так неадекватно реагируете. Топикстартер САМ наотрез отказался закрывать СОМ-порт, вот так обосновав свой отказ: Цитата(paskal @ Nov 19 2012, 21:16)  Можно между посылками закрывать порт и открывать когда нужно послать очередной раз. Но это тоже много лишних действий - после очередного открытия надо настраивать таймауты, режимы через dcb. Вот если бы можно было переводить порт как бы в спячку, чтоб он временно ничего не принимал. Но как это сделать я не знаю. Т.е. изначально поставил задачу так, чтобы решение не содержало закрытия порта.
|
|
|
|
|
Nov 20 2012, 15:24
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

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