Verständnis htonl() und ntohl()
Ich versuche, mit unix-sockets zu testen, senden einige udp-Pakete an localhost.
Es ist mein Verständnis, dass wenn die Einstellung ip-Adresse und port für den Versand der Pakete, die ich füllen würde meine sockaddr_in
mit Werten konvertiert, um Netzwerk-byte-Reihenfolge.
Ich bin auf OSX und ich bin erstaunt, dass diese
printf("ntohl: %d\n", ntohl(4711));
printf("htonl: %d\n", htonl(4711));
printf("plain: %d\n", 4711);
Drucke
ntohl: 1729232896
htonl: 1729232896
plain: 4711
Also weder Funktion tatsächlich liefert den einfachen Wert. Ich hätte erwartet, um zu sehen, entweder die Ergebnisse unterscheiden sich, wie x86 ist little-endian (afaik), oder identisch sein und die gleiche wie die aktuelle Nummer 4711. Klar ich verstehe nicht, was htonl
und ntohl
und Ihre Varianten. Was bin ich?
Der relevante code ist:
int main(int argc, char *argv[])
{
if (argc != 4)
{
fprintf(stderr, "%s\n", HELP);
exit(-1);
}
in_addr_t rec_addr = inet_addr(argv[1]); //first arg is '127.0.0.1'
in_port_t rec_port = atoi(argv[2]); //second arg is port number
printf("Address is %s\nPort is %d\n", argv[1], rec_port);
char* inpath = argv[3];
char* file_buf;
unsigned long file_size = readFile(inpath, &file_buf); //I am trying to send a file
if (file_size > 0)
{
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = rec_addr; //here I would use htons
dest.sin_port = rec_port;
printf("ntohs: %d\n", ntohl(4711));
printf("htons: %d\n", htonl(4711));
printf("plain: %d\n", 4711);
int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd != -1)
{
int error;
error = sendto(socket_fd, file_buf, file_size + 1, 0, (struct sockaddr*)&dest, sizeof(dest));
if (error == -1)
fprintf(stderr, "%s\n", strerror(errno));
else printf("Sent %d bytes.\n", error);
}
}
free(file_buf);
return 0;
}
htonl()
und ntohl()
.Ja, das kam aus versuchen beide, mit dem gleichen Ergebnis, danke für die Bemerkung.
InformationsquelleAutor oarfish | 2016-04-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
Beide Funktionen in umgekehrter Byte' um. Warum wäre das kehren das argument selbst?
Versuchen
htons(ntohs(4711))
undntohs(htons(4711))
.InformationsquelleAutor Michel de Ruiter
Wie andere erwähnt haben, sowohl
htons
undntohs
Umkehrung der byte-Reihenfolge auf einer little-endian Maschine, und sind keine-ops auf big-endian Maschinen.Was nicht erwähnt ist, dass diese Funktionen nehmen einen 16-bit-Wert und liefert ein 16-bit-Wert. Wenn Sie konvertieren von 32-bit-Werte, die Sie verwenden möchten
htonl
undntohl
statt.Die Namen dieser Funktionen stammen aus der traditionellen Größe bestimmter Datentypen. Die
s
steht fürshort
während derl
steht fürlong
. Einshort
ist in der Regel 16-bit -, während auf älteren Systemenlong
32-bit-Betriebssystem.In Ihrem code, Sie brauchen nicht zu rufen
htonl
aufrec_addr
, weil dieser Wert wurde zurückgegebeninet_addr
, und die Funktion gibt die Adresse in Netzwerk-byte-Reihenfolge.Aber anrufen müssen
htons
aufrec_port
.rec_port
mithtons
, 8080 verwandelt sich in 36895.InformationsquelleAutor dbush
"Network byte order" bedeutet immer big endian.
"Host byte order" hängt von der Architektur des host. Je nach CPU -, host-byte-order little-endian, big endian oder etwas anderes. (g)libc passt host-Architektur.
Weil die Intel-Architektur ist little-endian, das bedeutet, dass beide Funktionen sind dabei die gleichen: die Umkehrung der byte-Reihenfolge.
InformationsquelleAutor gudok
diese Funktionen sind schlecht benannt.
Host to network
undnetwork to host
sind eigentlich die gleiche Sache, und wirklich sollte aufgerufen werden, 'ändern endianness, wenn dies ist ein little-endian-Maschine'Also auf einer little-endian Maschine, die Sie tun
und senden Sie die Nummer auf dem Draht. Und wenn man ein big-endian Anzahl der Kabel
auf einem großen end-Maschine
und
und in den letzten Fällen, die Sie sehen, dass diese Funktionen tun nichts
htonl()
ist nicht seine eigene inverse. POSIX hat diese Funktionen handhaben zu können, sollten Sie jemals brauchen werden, zu tun.ok, dann sollte es genannt werden 'ändern endian zu big ist dies nicht eine big-endian-Maschine'
Auch wenn die beiden Funktionen führen die gleiche Sache mit unterschiedlichen Namen für Sie noch nützlich, weil es verdeutlicht die code ' s Absicht-d.h. wenn ich sehe, x=ntohl(bla) ich weiß, dass der zugewiesene Wert x wird semantisch sinnvoll, in der Erwägung, dass, wenn ich sehe, x=htonl(bla) ich weiß, dass der Wert von x ist nicht eine, die ich mich verlassen kann auf native-endian-Format. Wenn der code war nur für x=maybe_endian_swap(bla), dann wäre es nicht selbstverständlich für mich, ob ich z.B. printf("%i\n", x); und danach sehen, einen semantisch sinnvollen Wert gedruckt.
Endian ist nicht eine Sicht von Ursprung, es ist eine Sicht der destination: commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
InformationsquelleAutor pm100