![]() |
|
Модераторы: feodorv |
![]()
|
|
| OlegIT |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 684 Регистрация: 5.4.2006 Репутация: нет Всего: нет |
Windows. Код работы по UDP взят из матлаб. В РС из прибора приходят данные. В сниффере видно, что данные идут стабильно. Программа на РС принимает эти приходящие данные. Иногда, при включении, данные принимаются, иногда нет. udpOpenSend(…),udpOpenReceive(…) всегда проходят успешно, а udpReceive(…), когда данные не идут, возвращает ERR_FIFO_EMPTY. Приём происходит в отдельном потоке и быстрее чем передача прибором. Если закрыть канал и заново открыть его, без выхода из программы, данные могут начать приниматься, а могут и не приниматься. Как стабилизировать работу UDP?
|
|||
|
||||
| DrHex |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 171 Регистрация: 2.5.2009 Репутация: нет Всего: нет |
Ну во первых UDP и есть не стабильный протокол.
А во вторых мониторь время отвправки пакетов и время когда идет попытка на чтения(Какой промежуток??? и подумай...) --------------------
google.com и это все. |
|||
|
||||
| OlegIT |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 684 Регистрация: 5.4.2006 Репутация: нет Всего: нет |
«Ну во первых UDP и есть не стабильный протокол.» - это понятно, но не до такой же степени!
«Приём происходит в отдельном потоке и быстрее чем передача прибором.» Отсылка данных прибором идёт с периодом 100 мс, попытка приёма с периодом 1 мс. Как я понимаю, и в этом я могу ошибаться, хотя бы через 100 циклов попыток приёма данные в буфере должны появиться, именно так и происходит когда с приёмом всё нормально. Ещё одно наблюдение, если прибор включить после запуска программы, то сбоев не происходит. Прибор получает команды из программы всегда, без сбоев. |
|||
|
||||
| DrHex |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 171 Регистрация: 2.5.2009 Репутация: нет Всего: нет |
Значит коннект где то валится.....
У вас вопрос на подобии "у меня программа не работает, я все проверил но не работает что делать??? ОС переустановить??? Компилятор поменять??? " --------------------
google.com и это все. |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 5 Всего: 154 |
||||
|
||||
| OlegIT |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 684 Регистрация: 5.4.2006 Репутация: нет Всего: нет |
«У вас вопрос на подобии "у меня программа не работает,…» да не на подобии вопрос. Надежда на то, что у кого-нибудь были такие же проблемы и товарищ поделится опытом. Большое дело ОПЫТ!!!
Складывается впечатление, что дело в моменте открытия сокета или первой попытке чтения. |
|||
|
||||
| mrbrooks |
|
|||
![]() трололомен ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4259 Регистрация: 4.10.2006 Где: Дол Гулдур Репутация: нет Всего: 306 |
||||
|
||||
| Олег2005 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
Зачем вам циклиться с 1 мс? Делаете обычный блокирующий UDP сокет - выходите на recvfrom() - и висите на нем до того как прийдет полный UDP-пакет. И никаких проблем....... |
|||
|
||||
| OlegIT |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 684 Регистрация: 5.4.2006 Репутация: нет Всего: нет |
Посмотрел код. Есть там функция recvfrom(), но программа выходит раньше по проверке
if (mes == 0) return ERR_FIFO_EMPTY;
|
|||
|
||||
| Олег2005 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
Стивенс пишет, что для FIONREAD указатель должен быть обязательно на int
У вас же: unsigned long mes = 0; Может в этом фишка? Ну и затем.....если у вас 0, вы вообще возвращаетесь..... Ладно, ведь данных может и не быть, тем более что UDP-пакет должен прибыть полностью - иначе событие не взведется.... Значит, надо возвращаться через таймаут на повторное ожидание - и тд. Это у вас и есть милисекундный цикл? Т.е. я так думаю, что это ведь не TCP- когда у него прийдет хоть один байт - уже нормально. В UDP - должен прийти весь пакет. Какой длины у вас может быть пакет? Тут что-то не стыкуется по логике..... Я предлагаю вообще выкинуть ioctl - и висеть на recvfrom - cразу......сколько надо....... можно select' ом сделать таймаут....... Это сообщение отредактировал(а) Олег2005 - 19.10.2009, 14:44 |
|||
|
||||
| OlegIT |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 684 Регистрация: 5.4.2006 Репутация: нет Всего: нет |
Я пробовал убрать ioctlsocket. Висит в recvfrom и не выходит.
В MSDN-е этот аргумент дан как u_long. По другому компилятор (Visual Studio 2008) ругается.
Да, он самый. В сниффере видно, что пакеты идут всегда и полностью, длина пакета 44 байта. Принимает или нет программа эти пакеты, PC ICMP запросы не шлёт. Получается, что программа UDP пакеты вычитывает из буфера? |
||||
|
|||||
| niXman |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 211 Регистрация: 4.7.2009 Репутация: нет Всего: 0 |
Именно до такой) По всему сказанному, остается дополнить: http://www.rsdn.ru/article/unix/sockets.xml --------------------
if ( !c++ ) { *power--; this->wussiness += 10;} |
|||
|
||||
| Олег2005 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
Итак, еще пара вопросов.
Шлет у вас пакеты - некое железо (прибор) Может он шлет - ооооочень быстро? Быстрый передатчик UDP может забить медленный приемник. Во всяком случае надо это иметь в виду. Далее - не приходит вообще НИ ОДИН пакет? В принципе? Насчет recvfrom() Суть ее в том, что она просто копирует из приемного буфера сокета в модуле UDP(cистемного буфера) в буфер приема, указанный в параметрах функции. Операция копирования в буфер разрешается системой только тогда, когда прийдет весь UDP-пакет. Потому recvfrom и ждет всего пакета. Что то я не понял сути фразы вычитает - или считывает? Далее (udp[udpDesc].sock, (char *) what, length, 0, (LPSOCKADDR) & udp[udpDesc].sockFrom, &len) У вас достаточно сложная система параметров - а нет ли в ней ошибки - просто указываете не на тот сокет, не на тот адрес, не ту длину (обычно рекомендуют применятьsizeof()) Надо бы в дебаге посмотреть значение параметров..... |
|||
|
||||
| OlegIT |
|
||||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 684 Регистрация: 5.4.2006 Репутация: нет Всего: нет |
Прибор шлёт с периодом 100 мс, приём идёт с периодом 1 мс.
Увы, но именно так. Это тогда, когда приёма нет. Программа висит в функции recvfrom(), если я закрываю вызов функции ioctlsocket().
Как я понимаю ICMP запросы PC посылает тогда, когда программа, которая должна принимать данныеБ посланные на этот PC, не работает. Именно это я наблюдаю в сниффере, программа не работает, ICMP запросы идут, запускаю программу, запросы прекращаются. И это не зависимо от того принимает программа данные или нет.
Код не мой, взят из матлаб. Длина берётся как sizeof(), только это делается при вызове функции udpReceive(). Я сейчас закрыл все другие действия в программе. Она работает только на чтение с одного канала.
Проверил. Меняется только значение сокета udp[udpDesc].sock. Но это понятно, оно меняется когда я, по кнопке, закрываю каналы и вновь их открываю. По любому по этим значениям данные могут приниматься и не приниматься. |
||||||||||
|
|||||||||||
| Олег2005 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
Этого я не понял...... ICMP - наверно не запросы а сообщения об ошибке - destination unreachable Как только вы запускаете программу на каком либо порту, пункт назначения становится достижимым..... Прокомментируйте мне ваши проверки - и покажите, как вы заполняете структуры адресов сокетов - программы(получателя данных) и прибора С прибора вы ведь получаете данные - и ему тоже что-то отправляете? А вообще выложили бы весь код - приаттачили....... Это сообщение отредактировал(а) Олег2005 - 20.10.2009, 16:18 |
|||
|
||||
| DrHex |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 171 Регистрация: 2.5.2009 Репутация: нет Всего: нет |
При программирование UDP на сервере должен быть всегда рецейв. Попробуйте не блокирующие сокет, с таким что бы на получения данных осадить N количество буферов и при уменьшение постоянно их увеличивать. По идее должно полечить. Похоже на то что когда происходит отправка пакета, приемник еще или уже не готов к получению и соответственно пакеты провалюваются.
--------------------
google.com и это все. |
|||
|
||||
| OlegIT |
|
||||||||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 684 Регистрация: 5.4.2006 Репутация: нет Всего: нет |
Весь код достаточно сложно выложить, проект большой. И я сейчас многое закрыл, работаю только на приём данных и их отображение. Выкладываю то, что реально сейчас работает.
Вы спрашивали «Далее - не приходит вообще НИ ОДИН пакет? В принципе?» Да, ни одного пакета не приходит.
Можно подумать и эту серию ифов прокомментировать, но программа, когда не работает до них не доходит. Я думаю так, могу ошибаться. Если адрес не пустой (INADDR_ANY равен 0x00000000) и данные пришли от туда, откуда ожидали, то идём дальше, иначе return ERR_FIFO_EMPTY;
Адреса беру из объекта SysIPAddress32 в текстовом виде в формате «xxx.xxx.xxx.xxx»
В прибор посылаются команды и он(прибор) отвечает на них. Проверил по снифферу, отсылка команд из программы и приём ответа из прибора идёт всегда, не зависимо от того доходят или нет эти данные-ответы до программы. DrHex
У меня тоже такое подозрение. Но я не всё в Вашем ответе понял, наверно не всё знаю. Что такое «не блокирующие сокет» и как его создать? «осадить N количество буферов и при уменьшение постоянно их увеличивать» как это сделать? Можно немного подробнее. Присоединённый файл ( Кол-во скачиваний: 3 )
arh.rar 4,55 Kb |
||||||||||||||
|
|||||||||||||||
| Олег2005 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
У прибора есть IP-адрес? Какой? Порт - какой?
Обмен данными начинает всегда программа? На компе с программой - одна сетевая карта? Какой IP-адрес? У адресов - одна маска? Прибор далеко? В Африке - или в той же локалке? Программа посылает команду на прибор - прибор получает, понимает ее и что-то шлет в программу. Так? И в самом начале вы пишите - что иногда все идет нормально - а иногда вообще куда-то данные исчезают.? При каких условиях - не пытались выяснить? - работает хорошо - работает плохо (т.е. вообще не работает) Какой смысл этого массива в программе: udp[Desc]? Насчет неблокироющих сокетов - не заморачивайтесь, здесь им не место, блокирующие(ваши) в самый раз. |
|||
|
||||
| OlegIT |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 684 Регистрация: 5.4.2006 Репутация: нет Всего: нет |
В компе две сетевых карты, одна «смотрит» во вне, вторая только на прибор, специально так сделал, что бы ни чего не мешало. Комп стоит слева от меня, прибор справа. У компа, этой сетевой карты, адрес 192.224.4.35, маска 255.255.255.0 (ставил и 255.255.0.0), у прибора 192.224.4.33, маски нет.
Да так. Причём не зависимо от того, «видит» программа эти ответы/данные или нет (проверенно по байтно в сниффере).
Условия выяснить пытался, но пока безрезультатно. Как я говорил, в программе есть кнопка, по которой, потоки останавливаются, все связи, сокеты закрываются, а затем всё инициализируется заново, функция OnBnClickedConnect() исходника. Если нажимать эту кнопку, то не предсказуемо, через одно… пять… нажатий состояние приёма может поменяться на противоположноё. Здесь состояние это приходят или не приходят данные.
Хранилище нескольких сокетов, связей. У меня сейчас два элемента этого массива используется, один для приёма данных из прибора, другой для отсылки команд в прибор. |
||||||||
|
|||||||||
| Олег2005 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
Итак, все по новой......
В программе используются два сокета - один на прием, второй на передачу. Зачем? Если смотреть проще - то один и тот же сокет может применяться и для передачи, и для приема. Потому как в UDP-модуле стека у сокета два буфера - передающий - он формируется как стек - и приемный - обычный буфер. То, что вы сокеты биндите на конкретную карту, которая смотрит на прибор - это безусловно верно. Вы оба сокета биндите на этот один сокетный адрес, так? Для этого используете reuseaddr И теперь - главное. Стивенс пишет, что когда производится дублирование адреса для двух сокетов - какой сокет получит ответную датаграмму - зависит от реализации стека. Потому у меня подозрение, что вы читаете на на одном сокете - а передатчик может направить пакет на другой. как раз тот, который вы используете для приема. Потому идея двух сокетов сбинденных на один сокетный адрес для меня в данном случае непонятна. Почему не передавать - и принимать - все по одному и тому же сокету.... Тогда никаких проблем вообще не будет... Попробуйте поэкспериментировать - и ставить recvfrom() - для обеих сокетов......может все и получите..... Это сообщение отредактировал(а) Олег2005 - 22.10.2009, 23:48 |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Сети | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |