Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не стабильная работа UDP. 
:(
    Опции темы
OlegIT
Дата 12.10.2009, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 684
Регистрация: 5.4.2006

Репутация: нет
Всего: нет



Windows. Код работы по UDP взят из матлаб. В РС из прибора приходят данные. В сниффере видно, что данные идут стабильно. Программа на РС принимает эти приходящие данные. Иногда, при включении, данные принимаются, иногда нет. udpOpenSend(…),udpOpenReceive(…) всегда проходят успешно, а udpReceive(…), когда данные не идут, возвращает ERR_FIFO_EMPTY. Приём происходит в отдельном потоке и быстрее чем передача прибором. Если закрыть канал и заново открыть его, без выхода из программы, данные могут начать приниматься, а могут и не приниматься. Как стабилизировать работу UDP?

PM MAIL   Вверх
DrHex
Дата 18.10.2009, 00:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 2.5.2009

Репутация: нет
Всего: нет



Ну во первых UDP и есть не стабильный протокол.
А во вторых мониторь  время отвправки пакетов и время когда идет попытка на чтения(Какой промежуток??? и подумай...)
--------------------
google.com и это все.
PM MAIL   Вверх
OlegIT
Дата 18.10.2009, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 684
Регистрация: 5.4.2006

Репутация: нет
Всего: нет



«Ну во первых UDP и есть не стабильный протокол.» - это понятно, но не до такой же степени!
«Приём происходит в отдельном потоке и быстрее чем передача прибором.» Отсылка данных прибором идёт с периодом 100 мс, попытка приёма с периодом 1 мс. Как я понимаю, и в этом я могу ошибаться, хотя бы через 100 циклов попыток приёма данные в буфере должны появиться, именно так и происходит когда с приёмом всё нормально. Ещё одно наблюдение, если прибор включить после запуска программы, то сбоев не происходит. Прибор получает команды из программы всегда, без сбоев.

PM MAIL   Вверх
DrHex
Дата 19.10.2009, 00:11 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 171
Регистрация: 2.5.2009

Репутация: нет
Всего: нет



Значит коннект где то валится.....


У вас вопрос на подобии "у меня программа не работает, я все проверил но не работает что делать??? ОС переустановить??? Компилятор поменять??? "
--------------------
google.com и это все.
PM MAIL   Вверх
Lazin
Дата 19.10.2009, 05:35 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 5
Всего: 154



Цитата(DrHex @  19.10.2009,  00:11 Найти цитируемый пост)
Значит коннект где то валится..

коннект? у UDP? smile 
PM MAIL Skype GTalk   Вверх
OlegIT
Дата 19.10.2009, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 684
Регистрация: 5.4.2006

Репутация: нет
Всего: нет



«У вас вопрос на подобии "у меня программа не работает,…» да не на подобии вопрос. Надежда на то, что у кого-нибудь были такие же проблемы и товарищ поделится опытом. Большое дело ОПЫТ!!!smile
Складывается впечатление, что дело в моменте открытия сокета или первой попытке чтения.

PM MAIL   Вверх
mrbrooks
Дата 19.10.2009, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: нет
Всего: 306



Цитата(OlegIT @  12.10.2009,  21:51 Найти цитируемый пост)
Как стабилизировать работу UDP?

Использовать TCP.
PM MAIL   Вверх
Олег2005
Дата 19.10.2009, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

Репутация: 6
Всего: 11



Цитата(OlegIT @  18.10.2009,  09:06 Найти цитируемый пост)
«Приём происходит в отдельном потоке и быстрее чем передача прибором.» Отсылка данных прибором идёт с периодом 100 мс, попытка приёма с периодом 1 мс. Как я понимаю, и в этом я могу ошибаться, хотя бы через 100 циклов попыток приёма данные в буфере должны появиться, именно так и происходит когда с приёмом всё нормально. Ещё одно 

Зачем вам циклиться с 1 мс?
Делаете обычный блокирующий UDP сокет - выходите на recvfrom() - и висите на нем до того как прийдет полный UDP-пакет.
И никаких проблем.......
PM MAIL WWW MSN   Вверх
OlegIT
Дата 19.10.2009, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 684
Регистрация: 5.4.2006

Репутация: нет
Всего: нет



Посмотрел код. Есть там функция recvfrom(), но программа выходит раньше по проверке
if (mes == 0)
    return ERR_FIFO_EMPTY;

 

Код

/**
 * what:   Put the received data is.
 * length: How long the "what" array is.
 *
 * Returns 0 if new data, ERR_FIFO_EMPTY if no new data. ERR_INVALID_DESC
 * is obvious.
 */
int udpReceive(int udpDesc, unsigned char *what,
                      int length, unsigned long *from) {
    unsigned long mes = 0;

    //unsigned long mess=0;
    int err;
    int len = sizeof(SOCKADDR);
    int turn = 0;

    if (udpDesc < 0 || udpDesc >= UDP_MAX_CHANNELS)
        return ERR_INVALID_DESC;

    err = ioctlsocket(udp[udpDesc].sock, FIONREAD, &mes);
    if (err == SOCKET_ERROR) {
//        printf("Error checking socket I/O status: %d\n", WSAGetLastError());
        return ERR_SOCKET_IOCTL;
    }
    if (mes == 0)                       /* nothing to read */
        return ERR_FIFO_EMPTY;
//    err = recvfrom(udp[udpDesc].sock, (void *) what, length, 0,
    err = recvfrom(udp[udpDesc].sock, (char *) what, length, 0,
                   (LPSOCKADDR) & udp[udpDesc].sockFrom, &len);

    if (udp[udpDesc].sockSend.sin_addr.s_addr != htonl(INADDR_ANY)) {
        if (udp[udpDesc].sockSend.sin_addr.s_addr !=
            udp[udpDesc].sockFrom.sin_addr.s_addr) {
            return ERR_FIFO_EMPTY;
        }
    }
    if (from != NULL)
        /* Return the sender's ip address in from */
        *from = udp[udpDesc].sockFrom.sin_addr.s_addr;
    return 0;
}


PM MAIL   Вверх
Олег2005
Дата 19.10.2009, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 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
PM MAIL WWW MSN   Вверх
OlegIT
Дата 19.10.2009, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 684
Регистрация: 5.4.2006

Репутация: нет
Всего: нет



Я пробовал убрать ioctlsocket. Висит в recvfrom и не выходит.
Цитата

Стивенс пишет, что для  FIONREAD указатель должен быть обязательно на int
 
В MSDN-е этот аргумент дан как u_long. По другому компилятор (Visual Studio 2008) ругается.
Цитата

Это у вас и есть милисекундный цикл?
 
Да, он самый.

В сниффере видно, что пакеты идут всегда и полностью, длина пакета 44 байта. Принимает или нет программа эти пакеты, PC ICMP запросы не шлёт. Получается, что программа UDP пакеты вычитывает из буфера?

PM MAIL   Вверх
niXman
Дата 19.10.2009, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 4.7.2009

Репутация: нет
Всего: 0



Цитата(OlegIT @  18.10.2009,  08:06 Найти цитируемый пост)
«Ну во первых UDP и есть не стабильный протокол.» - это понятно, но не до такой же степени!

Именно до такой)

По всему сказанному, остается дополнить: http://www.rsdn.ru/article/unix/sockets.xml
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
Олег2005
Дата 20.10.2009, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

Репутация: 6
Всего: 11



Итак, еще пара вопросов.
Шлет у вас пакеты - некое железо (прибор)
Может он шлет - ооооочень быстро? Быстрый передатчик UDP может забить медленный приемник.
Во всяком случае надо это иметь в виду.
Далее - не приходит вообще НИ ОДИН пакет? В принципе?
Насчет recvfrom()
Суть ее в том, что она просто копирует из приемного буфера сокета в модуле UDP(cистемного буфера) в буфер приема, указанный в параметрах функции. Операция копирования в буфер разрешается системой только тогда, когда прийдет весь UDP-пакет.
Потому recvfrom и ждет всего пакета.

Цитата(OlegIT @  19.10.2009,  14:03 Найти цитируемый пост)
что программа UDP пакеты вычитывает из буфера?

Что то я не понял сути фразы вычитает - или считывает?
Далее
(udp[udpDesc].sock, (char *) what, length, 0, (LPSOCKADDR) & udp[udpDesc].sockFrom, &len)
У вас достаточно сложная система параметров - а нет ли в ней ошибки - просто указываете не на тот сокет, не на тот адрес, не ту длину (обычно рекомендуют применятьsizeof())
Надо бы в дебаге посмотреть значение параметров.....

PM MAIL WWW MSN   Вверх
OlegIT
Дата 20.10.2009, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 684
Регистрация: 5.4.2006

Репутация: нет
Всего: нет



Цитата

Может он шлет - ооооочень быстро? Быстрый передатчик UDP может забить медленный приемник. 

Прибор шлёт с периодом 100 мс, приём идёт с периодом 1 мс.

Цитата

Далее - не приходит вообще НИ ОДИН пакет? В принципе?

Увы, но именно так. Это тогда, когда приёма нет. Программа висит в функции recvfrom(), если я закрываю вызов функции ioctlsocket().

Цитата

Что то я не понял сути фразы вычитает - или считывает?

Как я понимаю ICMP запросы PC посылает тогда, когда программа, которая должна принимать данныеБ посланные на этот PC, не работает. Именно это я наблюдаю в сниффере, программа не работает, ICMP запросы идут, запускаю программу, запросы прекращаются. И это не зависимо от того принимает программа данные или нет.

Цитата

У вас достаточно сложная система параметров - а нет ли в ней ошибки…

Код не мой, взят из матлаб. Длина берётся как sizeof(), только это делается при вызове функции udpReceive().
Я сейчас закрыл все другие действия в программе. Она работает только на чтение с одного канала.

Цитата

Надо бы в дебаге посмотреть значение параметров.....

Проверил. Меняется только значение сокета udp[udpDesc].sock. Но это понятно, оно меняется когда я, по кнопке, закрываю каналы и вновь их открываю. По любому по этим значениям данные могут приниматься и не приниматься.
PM MAIL   Вверх
Олег2005
Дата 20.10.2009, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

Репутация: 6
Всего: 11



Цитата(OlegIT @  20.10.2009,  14:04 Найти цитируемый пост)
Увы, но именно так. Это тогда, когда приёма нет.

Этого я не понял......
Цитата(OlegIT @  20.10.2009,  14:04 Найти цитируемый пост)
Именно это я наблюдаю в сниффере, программа не работает, ICMP запросы идут, запускаю программу, запросы прекращаются. И это не зависимо от того принимает программа данные или нет.

ICMP - наверно не запросы  а сообщения об ошибке - destination unreachable
Как только вы запускаете программу на каком либо порту, пункт назначения становится достижимым.....

Цитата(OlegIT @  19.10.2009,  11:42 Найти цитируемый пост)

Код

if (udp[udpDesc].sockSend.sin_addr.s_addr != htonl(INADDR_ANY)) {
        if (udp[udpDesc].sockSend.sin_addr.s_addr !=
            udp[udpDesc].sockFrom.sin_addr.s_addr) {
            return ERR_FIFO_EMPTY;}


Прокомментируйте мне ваши проверки - и покажите, как вы заполняете структуры адресов сокетов - программы(получателя данных) и прибора
С прибора вы ведь получаете данные - и ему тоже что-то отправляете?

А вообще выложили бы весь код - приаттачили.......

Это сообщение отредактировал(а) Олег2005 - 20.10.2009, 16:18
PM MAIL WWW MSN   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0582 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.