Im Netz wird Big-Endian gesprochen. Daran muss man denken, wenn man Strukturen über TCP/IP an andere Hosts senden will. Der folgende Code wird deshalb nicht funktionieren, wenn er auf einer Intel-Maschine unter Linux ausgeführt wird. An dieser Stelle noch die Anmerkung: Java hat intern immer Big-Endian-Repräsentation
struct Messwert
{
long long nanoseconds_ad;
double wert;
Messwert(int z, double w) : nanoseconds_ad(z), wert(w) {}
Messwert(const Messert& other)
:nanoseconds_ad(other.nanoseconds_ad)
,wert(other.wert) {}
};
Messert m(42, 1234.5);
send(socket, &m, sizeof(m))
Um die Endianness für seine Maschine zu prüfen, kann man wie im folgenden Code gezeigt wird, eine Integer-Variable mit dem Wert 1 auch als char-Pointer interpretieren. Bei Little-Endian steht an der ersten Position in diesem Zeiger das niedrigwertigste Bit. Bei Big-Endian ist es entsprechend anders herum.
Die Zahl 75 binär dargestellt ist 0100 1011. Je nach Endianness ist die Darstellung im Speicher unterschiedlich:
- Little Endian: 1101 0010
- Big Endian: 0100 1011
Für 64-Bit-Integer benötigt man nicht standardisierte host-to-net (und vice-versa) Konverter. Mit endian.h stellt uns Linux zum Glück die entsprechenden Konverter zur Verfügung.
#include <stdio.h>
#include <endian.h>
int
main(int, char**)
{
// Endian-Test
int n = 1;
if (*(char*)&n == 1)
fprintf(stdout, "little\n");
else
fprintf(stdout, "big\n");
// Konverter Tests
unsigned long long ll = 1234LL;
fprintf(stdout, "to_net(%llu) = %llu\n", ll, htobe64(ll));
fprintf(stdout, "to_host(%llu) = %llu\n", htobe64(ll), be64toh(htobe64(ll)));
// Wegen inv(inv(x)) = x würde auch ein einziger Konverter genügen
fprintf(stdout, "to_net(to_net(%llu)) = %llu\n", ll, htobe64(htobe64(ll)));
fprintf(stdout, "to_host(to_host(%llu)) = %llu\n", ll, be64toh(be64toh(ll)));
}
Mit diesem Wissen können wir also die Messdaten korrekt übertragen
struct Messwert
{
long long nanoseconds_ad;
double wert;
Messert() : nanoseconds_ad(0LL), wert(0.0) {}
Messwert(long long z, double w) : nanoseconds_ad(z), wert(w) {}
void pack(Messwert& target)
{
target.nanoseconds_ad = htobe64(nanoseconds_ad);
target.wert = wert;
}
};
Messwert m(42LL, 1234.5);
Messwert p(m);
p.pack();
send(socket, &p, sizeof(p))