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


Автор: mephistotel77 16.4.2010, 16:43
У меня возник такой вопрос:
Я отсылаю команду серверу (железке), в ответ (как я понял это шесть байт, 4*байт + 1*int16_t) она присылает мне свое состояние в соответствии с протоколом). Но нужно точно знать, что я правильно понял спецификацию и что протокол не изменен. Т.е. что мне передаются именно 6 байт и я именно их и считываю.
Код

...
const uint32_t sizebuff = 65535 - (20 + 8);
uchar *buff = (uchar *) malloc(sizebuff);
bzero(buff, (size_t) sizebuff);
...
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
...
int size = sendto(sockfd, command, sizeof(command), 0, (sockaddr) &servaddr, sizeof(servaddr));
if (size == -1)
{
   ...
}
else
{
   int size = recvfrom(sockfd, buff, sizeof(buff), 0, (sockaddr) &inputaddr);
}

Интересуют подходы к тому как можно считать эти самые 6 байт, при этом чтобы гарантированно знать что ещё каких-то данных в сокете не осталось:
1. Попытаться считать количество байт данных, максимальное для протокола UDP и recvfrom возратит количество реальные данных.
Код

int size = recvfrom(sockfd, buff, sizeof(buff), 0, (sockaddr) &inputaddr);
if (size == 6)
{
  //Все хорошо
}

2. Я считываю ровно 6 байт и потом смотрю, а остались ли в сокете ещё какие-то данные?
Код

uint i = 0;
while (recvfrom(sockfd, buff, 6, 0, (sockaddr) &inputaddr) != 0)
{
  i++;
  if (i > 1)
 {
   perror(recvfrom); // Ошибка. Значит данные организованы по другому
   break;
 }
 //Считываем пока есть данные
}

либо вариации на эту тему (кстати более оптимальный/правильный/кошерный код приветствуется).
Можно ли сделать как во втором случае?
Стивенс пишет по этому поводу (Unix. Разработка сетевых приложений, 3 издание, стр. 278)
"Для сокета на уровне UDP происходит неявная буферизация дейтаграмм в виде очереди. Действительно у каждого сокета UDP имеется буфер приема, и каждая дейтаграмма, приходящая на этот сокет, помещается в его буфер приема. Когда процесс вызывает функцию recvfrom, очередная дейтаграмма из буфера возвращается процессу в порядке FIFO..."
Т.е. если я считал 6 байт из 10 байт дейтаграммы и вызвал опять recvfrom, то я считаю оставшиеся 4 байта или получу данные с другой дейтаграммы?

Автор: MAKCim 17.4.2010, 09:00
Цитата(mephistotel77 @  16.4.2010,  16:43 Найти цитируемый пост)
Т.е. если я считал 6 байт из 10 байт дейтаграммы и вызвал опять recvfrom, то я считаю оставшиеся 4 байта или получу данные с другой дейтаграммы?

нет
будет установлен MSG_TRUNC и 4 байта будут потеряны

в вашем случае нужно считывать PMTU - 20 - 8 байт (максимальный размер UDP сообщения) по сути первый случай

Автор: sigizmynd 13.8.2010, 15:16
короче,смотри,
в функцие recvfrom есть поле флаги
он имеет 3 различных флага
я думаю, что в данном случае для тебя будет интересен флаг MSG_WAITALL
привожу описание из книги Рочкинда "программирование для Unix"
MSG_WAITALL используется только для сокетов с установленным соединением.
блокирует recvfrom до тех пор пока не будет получено запрошенное число байт, флаг MSG_PEEK сброшен вызов не был прерван сигналом....
единственный минус этого флага, что он работает только с TCP(((

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