htonl и nthol работают только с целыми числами?Могу ли я использовать эти преобразования для данных с плавающей запятой
Для управления с плавающей запятой вы можете, например, использовать объединение для преобразования с плавающей запятой вuint32_t
и наоборот, или используйте приведение указателя float к указателю uint32_t
и наоборот, конечно же, не разыгрывайте float до uint32_t
и наоборот
Но вы, кажется, работаете double вместо float , в этом случае вам нужно использовать htobe64 / htole64/ be64toh / le64toh (endian.h
), если они не определены в Windows, решите порядок или байты в вашем пакете и определите преобразование самостоятельно
Каков порядок байтовфрейм в Linux и Windows
Порядок зависит только от процессора, а не от ОС
Я знаю, что функция sendto () возвращает количество байтовкоторые отправляются.То, что я посылаю, это 20Bytes -> (2 * 8Bytes (double) + 1 * 4Bytes (ulong)) = 20Bytes.Но функция возвращает 24 байт, как это может быть?Это происходит из-за заголовков протокола UDP или это дополнительная информация, которая включает в себя Windows?
У вас есть доступ только к полезной нагрузке , все заголовки / нижние колонтитулы / и т. Д. Скрыты для вас
Возможно, вы отправляете struct , а не создаете пакет для отправки, в этом случае компиляторы просто не следуют одному и тому же заполнению, или размер long равен 32b на одном и 64b надругой?
Не отправлять struct , копировать числа в векторе байтов, управляющих порядком байтов, и извлекать их таким же образом
ДляНапример, если все выполняется вручную, unsigned long считывается / записывается на 8 байтах, чтобы обеспечить совместимость, даже если на одном хосте 64b, а на другом меньше:
#include <string.h>
void encDec32(char * a, char * b)
{
const int e = 1;
if (*((char *) &e)) {
memcpy(a, b, 4);
}
else {
a[0] = b[3];
a[1] = b[2];
a[2] = b[1];
a[3] = b[0];
}
}
void encDec64(char * a, char * b)
{
const int e = 1;
if (*((char *) &e)) {
memcpy(a, b, 8);
}
else {
a[0] = b[7];
a[1] = b[6];
a[2] = b[5];
a[3] = b[4];
a[4] = b[3];
a[5] = b[2];
a[6] = b[1];
a[7] = b[0];
}
}
void encodeU32(char ** buffer, uint32_t v)
{
encDec32(*buffer, (char *) &v);
*buffer += 4;
}
void encodeU64(char ** buffer, uint64_t v)
{
encDec64(*buffer, (char *) &v);
*buffer += 8;
}
void encodeFloat(char ** buffer, float v)
{
encDec32(*buffer, (char *) &v);
*buffer += 4;
}
void encodeDouble(char ** buffer, double v)
{
encDec64(*buffer, (char *) &v);
*buffer += 8;
}
void encodeUlong(char ** buffer, unsigned long v)
{
/* force on 8 bytes to be compatible with CPU 32 and 64 */
encodeU64(buffer, (uint64_t) v);
}
uint32_t decodeU32(char ** buffer)
{
uint32_t v;
encDec32((char *) &v, *buffer);
*buffer += 4;
return v;
}
uint64_t decodeU64(char ** buffer)
{
uint64_t v;
encDec64((char *) &v, *buffer);
*buffer += 8;
return v;
}
float decodeFloat(char ** buffer)
{
float v;
encDec32((char *) &v, *buffer);
*buffer += 4;
return v;
}
float decodeDouble(char ** buffer)
{
double v;
encDec64((char *) &v, *buffer);
*buffer += 8;
return v;
}
unsigned long decodeUlong(char ** buffer)
{
/* force on 8 bytes to be compatible with CPU 32 and 64 */
return (unsigned long) decodeU64(buffer);
}
/* for a struct */
typedef struct S {
unsigned long u; /* may be on 32 or 64 and not the same size on Linuw and Windows */
double d1;
double d2;
} S;
/* b is the block to send, it must be enough long */
/* return the number of bytes to send in a block through UDP */
size_t encodeS(char * b, S * s)
{
char * b0 = b;
encodeUlong(&b, s->u);
encodeDouble(&b, s->d1);
encodeDouble(&b, s->d2);
return b - b0;
}
/* b is the block read through UDP */
void decodeS(char * b, S * s)
{
s->u = decodeUlong(&b);
s->d1 = decodeDouble(&b);
s->d2 = decodeDouble(&b);
}