Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > recvfrom не считывает UDP пакеты


Автор: bra1ss 22.12.2011, 15:21
Имеется внешнее устройство, подключаемое по Ethernet. Принцип управления им следующий: с компа на устройство посылаем UDP-пакет из 8 байт данных определенного вида. В ответ устройство начинает посылать UDP-пакеты с данными, которые нужно обрабатывать. Передача еще одного UDP-пакета из 8 байт данных "выключает" устройство. Для взаимодействия с устройством используется WinSock.

Код инициализации:

Код

WSAStartup(MAKEWORD(2,2), &m_wsaData);
m_UDP_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset( &m_service, 0, sizeof(m_service) );
m_service.sin_family        = AF_INET;
m_service.sin_addr.s_addr   = inet_addr( IP_ADDRESS.c_str() );
m_service.sin_port          = htons( PORT_NUMBER );


Отправка данных на устройство:

Код

sendto( m_UDP_socket, p_buff, len, 0/*flags*/, (SOCKADDR *)&m_service, sizeof(m_service));


Прием данных:

Код

setsockopt( m_UDP_socket, SOL_SOCKET, SO_RCVTIMEO,(const char *)&m_timeout , sizeof(m_timeout)); // timeout = 1000
sockaddr_in sender;
int sender_sz = sizeof (sender);

int res = recvfrom( m_UDP_socket, m_p_buffer, m_len, 0, (SOCKADDR*)&sender, &sender_sz );


Команда включения уходит на устройство нормально, но функция recvfrom возвращает код ошибки WSAETIMEDOUT. При этом в сниффере я вижу, что UDP-пакеты с данными от устройства исправно сыпятся. Где может быть проблема?

Автор: feodorv 22.12.2011, 19:00
bind на сокет?

Автор: bra1ss 23.12.2011, 07:22
не помогает

Автор: feodorv 23.12.2011, 11:45
Гм. setsockopt должен вызываться до всяких манипуляций с сокетом, то есть сразу после socket. А для теста его лучше закомментарить, или выставить таймаут в минуту и посмотреть, сколько времени требуется recvfrom до WSAETIMEDOUT.

Всё-таки, приведите обновлённый код с bind.
На какой порт сыпятся UDP-пакеты с устройства?

Автор: bra1ss 23.12.2011, 14:16
Разобрались с приемом, проблема была в прошивке устройства, теперь даже без бинда данные нормально принимаются с кодом выше. Вопрос теперь, как определить/задать порт, с которого комп отправляет команду включения? Именно на него и будут сыпаться пакеты.

Автор: feodorv 23.12.2011, 14:50
Я, лично, окончательно запутался  smile 

Цитата(bra1ss @  23.12.2011,  14:16 Найти цитируемый пост)
теперь даже без бинда данные нормально принимаются с кодом выше.

Цитата(bra1ss @  23.12.2011,  14:16 Найти цитируемый пост)
Вопрос теперь, как определить/задать порт ... Именно на него и будут сыпаться пакеты


А сейчас-то на каких портах всё это работает? smile На нулевых?


Цитата(bra1ss @  23.12.2011,  14:16 Найти цитируемый пост)
как определить

getsockname


Цитата(bra1ss @  23.12.2011,  14:16 Найти цитируемый пост)
как задать

Цитата(feodorv @  22.12.2011,  19:00 Найти цитируемый пост)
bind на сокет? 


Автор: bra1ss 23.12.2011, 15:30
Цитата(feodorv @  23.12.2011,  14:50 Найти цитируемый пост)
А сейчас-то на каких портах всё это работает? 


Сейчас я отправляю данные с порта компа номер X на порт устройства, который задаю в m_service.sin_port. Устройство мне отвечает с его порта Х на мой порт Х. И sendto, и recvfrom отрабатывают как надо. Нужно определить X.

Цитата(feodorv @  23.12.2011,  14:50 Найти цитируемый пост)
getsockname


Спасибо, теперь вроде всё в порядке.

Код

sockaddr_in p;
int p_sz = sizeof (p);
getsockname(m_UDP_socket, (SOCKADDR*)&p, &p_sz);
int port = ntohs(p.sin_port);

Автор: feodorv 23.12.2011, 16:45
А, то есть Вам всё равно, с какого порта работать? Тогда другое дело  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)