чтение UDP пакета по частям
Есть сообщение от клиента по UDP
что то типа такого
ush type;
ush size;
char data[size];
} Msg_t
делал как тут http://www.abc.se/~m6695/udp.html
но recvfrom() требует полный размер сообщения, а мне он не известен.
Вопрос:
Как серверу прочитать пришедшее сообщение от клиента по частям ?
(прочитать тип, прочитать размер, прочитать данные)
или как узнать размер пришедшего сообщения?
Спасибо.
char msgSizeStr[4] = {'\0'};
char buf[BUF_LEN] = {'\0'};
ush msgType = 0, msgSize = 0;
recvfrom(s, msgTypeStr, sizeof(Msg_t::type), 0, &si_other, &slen);
recvfrom(s, msgSizeStr, sizeof(Msg_t::size), 0, &si_other, &slen);
// convert msgTypeStr to msgType and msgSizeStr to msgSize here
ush commonReadBytesNum = 0;
ush currentReadBytesNum = recvfrom(s, BUF_LEN, 0, &si_other, &slen);
while ((currentReadBytesNum > 0) && (commonReadBytesNum <= msgSize)) {
commonReadBytesNum += currentReadBytesNum;
currentReadBytesNum = recvfrom(s, BUF_LEN, 0, &si_other, &slen);
}
P.S. Писал без проверки, за мелкие ошибки не обессудьте.
char msgSizeStr[4] = {'\0'};
char buf[BUF_LEN] = {'\0'};
ush msgType = 0, msgSize = 0;
recvfrom(s, msgTypeStr, sizeof(Msg_t::type), 0, &si_other, &slen);
recvfrom(s, msgSizeStr, sizeof(Msg_t::size), 0, &si_other, &slen);
// convert msgTypeStr to msgType and msgSizeStr to msgSize here
ush commonReadBytesNum = 0;
ush currentReadBytesNum = recvfrom(s, BUF_LEN, 0, &si_other, &slen);
while ((currentReadBytesNum > 0) && (commonReadBytesNum <= msgSize)) {
commonReadBytesNum += currentReadBytesNum;
currentReadBytesNum = recvfrom(s, BUF_LEN, 0, &si_other, &slen);
}
P.S. Писал без проверки, за мелкие ошибки не обессудьте.
А разьве после вызова recvfrom(s, msgTypeStr, sizeof(Msg_t::type), 0, &si_other, &slen);
с флагом 0 из приемного буфера убирается только то что вычитал а не все сообщение?
разьве после вызова recvfrom(s, msgTypeStr, sizeof(Msg_t::type), 0, &si_other, &slen);
с флагом 0 из приемного буфера убирается только то что вычитал а не все сообщение?
Как мне помнится из моей собственной практики - нет. По крайней мере, никогда не сталкивался с каким-то другим поведением.
Вот, собственно, описание recvfrom().
Вот, собственно, описание recvfrom().
recvfrom(s, msgTypeStr, sizeof(Msg_t::type), 0, &si_other, &slen);
читает нормально, а далее
recvfrom(s, msgSizeStr, sizeof(Msg_t::size), 0, &si_other, &slen);
в msgSizeStr лежит тип сообщения
Похоже, что при чтении части остальные данные из сообщения теряются.
Да речь про Linux, если это имеет значение
я делал так: в структуре которую посылаю первая переменная является размер всей структуры. и размер этой переменной знаем....
далее сначала считываем только размер
а параметр MSG_PEEK как раз говорит что после чтения все сообщение остается в стеке(и прочитаная часть тоже)
после чего мы уже знаем полный размер сообщения и уже считываем все сообщение полностью
как-то так)
я делал так: в структуре которую посылаю первая переменная является размер всей структуры. и размер этой переменной знаем....
далее сначала считываем только размер
а параметр MSG_PEEK как раз говорит что после чтения все сообщение остается в стеке(и прочитаная часть тоже)
после чего мы уже знаем полный размер сообщения и уже считываем все сообщение полностью
как-то так)
я про такой вариант думал
выполнить recvfrom() с флагом MSG_PEEK на размер type + size
далее recvfrom() с флагом 0 на весь размер
но дело в том что хотелось поле дата читать тоже частями
в соответствующие структуры а не выделять временный буфер
Не знаю можно так или нет но попробовал
выполнить recvfrom() с флагом MSG_PEEK на размер type + size
далее делать read() того что нужно,
но уже второй reda() возвращает размер меньше чем прошу прочитать
хотя размер буфера много больше размера сообщения
смотрел так: getsockopt ( sfd, SOL_SOCKET, SO_RCVBUF, &size, &sa_len)