htons()-Funktion in der Socket-Programmierung

Lesezeit: 5 Minuten

Benutzeravatar von Benutzer123422
Benutzer123422

Ich bin neu in der Socket-Programmierung und versuche, die Funktionsweise von zu verstehen htons(). Ich habe mir im Internet gerne ein paar Tutorials durchgelesen Dies und Dies eine zum Beispiel. Aber ich konnte nicht verstehen, was htons() tut genau. Ich habe folgenden Code ausprobiert:

#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

int main( int argc, char *argv[] )
{
    int sockfd, newsockfd, portno, clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int  n;

    /* First call to socket() function */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
    {
        perror("ERROR opening socket");
        exit(1);
    }
    /* Initialize socket structure */
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = 5001;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);

    /* Now bind the host address using bind() call.*/
    if (bind(sockfd, (struct sockaddr *) &serv_addr,
                          sizeof(serv_addr)) < 0)
    {
         perror("ERROR on binding");
         exit(1);
    }

    /* Now start listening for the clients, here process will
    * go in sleep mode and will wait for the incoming connection
    */
    listen(sockfd,5);
    clilen = sizeof(cli_addr);

    /* Accept actual connection from the client */
    newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, 
                                &clilen);
    if (newsockfd < 0) 
    {
        perror("ERROR on accept");
        exit(1);
    }
    /* If connection is established then start communicating */
    bzero(buffer,256);
    n = read( newsockfd,buffer,255 );
    if (n < 0)
    {
        perror("ERROR reading from socket");
        exit(1);
    }
    printf("Here is the message: %s\n",buffer);

    /* Write a response to the client */
    n = write(newsockfd,"I got your message",18);
    if (n < 0)
    {
        perror("ERROR writing to socket");
        exit(1);
    }
    return 0; 
}

Der Wert von sin_port wurde als angezeigt 35091 beim Debuggen und ich verstehe nicht wie portno gewechselt von 5001 zu 35091. Kann mir bitte jemand den Grund für diese Wertänderung erklären?

  • Was verstehen Sie wovon htons() tut? Hast du das gelesen: en.wikipedia.org/wiki/Endianness.

    – Oliver Charlesworth

    6. Oktober 2013 um 10:22 Uhr


  • Laut Linux-Handbuch The htons() Funktion konvertiert die vorzeichenlose kurze Ganzzahl hostshort von der Host-Byte-Reihenfolge in die Netzwerk-Byte-Reihenfolge.

    – Shushant

    6. Oktober 2013 um 10:29 Uhr

  • Ich kenne Big Endianne und Little Endianne, aber ich kenne die Funktionsweise von htons() nicht genau!!!

    – Benutzer123422

    6. Oktober 2013 um 10:39 Uhr

  • Was passiert, wenn Sie den Typ ändern? portno zu uint16_t?

    – jev

    6. Oktober 2013 um 10:40 Uhr


  • Das INADDR_* Konstanten sind die lokale Byte-Reihenfolge und müssen auch mithilfe von in die Netzwerkreihenfolge getauscht werden htonl (nicht htons), wie in htonl(INADDR_ANY). Du kommst nur ohne davon, weil INADDR_ANY zufällig Null ist, welches Byte gegen Null tauscht. Wenn Sie verwendet haben INADDR_LOOPBACKes würde nicht funktionieren.

    – Kas

    26. Februar 2016 um 23:17 Uhr

Benutzeravatar von brm
brm

Es hat mit der Reihenfolge zu tun, in der Bytes im Speicher gespeichert werden. Die Dezimalzahl 5001 ist 0x1389 in hexadezimal, so sind die beteiligten Bytes 0x13 und 0x89. Viele Geräte speichern Nummern in Little-Endian Format, was bedeutet, dass das niedrigstwertige Byte zuerst kommt. In diesem speziellen Beispiel bedeutet dies also, dass die Nummer im Speicher ist 5001 wird gespeichert als

0x89 0x13

Das htons() Die Funktion stellt sicher, dass die Zahlen im Speicher in der Reihenfolge der Netzwerkbytes gespeichert werden, d. h. mit dem höchstwertigen Byte zuerst. Es tauscht daher die Bytes, aus denen die Zahl besteht, so dass die Bytes im Speicher in der Reihenfolge gespeichert werden

0x13 0x89

Auf einen Little-Endian Maschine, die Nummer mit den vertauschten Bytes ist 0x8913 in hexadezimal, das heißt 35091 in Dezimalschreibweise. Beachten Sie, dass, wenn Sie an a arbeiten Big-Endian Maschine, die htons() Die Funktion müsste keine Vertauschung durchführen, da die Nummer bereits richtig im Speicher gespeichert wäre.

Der zugrunde liegende Grund für all diese Auslagerungen hat mit den verwendeten Netzwerkprotokollen zu tun, die erfordern, dass die übertragenen Pakete die Netzwerk-Byte-Reihenfolge verwenden.

htons ist host-to-network short

Dies bedeutet, dass es mit kurzen 16-Bit-Ganzzahlen funktioniert. dh 2 Byte.

Diese Funktion vertauscht die Endianness eines Short.

Ihre Nummer beginnt mit:

0001 0011 1000 1001 = 5001

Wenn die Endianness geändert wird, werden die beiden Bytes vertauscht:

1000 1001 0001 0011 = 35091

  • Meinst du, dass 0001 0011 Host-Bytes und 1000 1001 Netzwerk-Byes sind?

    – Benutzer123422

    6. Oktober 2013 um 12:37 Uhr

  • @ User123422 nein, du hast es falsch verstanden. Obwohl die binäre Form von 5001 “‘0001 0011’ ‘1000 1001′” ist, speichert es beim Speichern in einer LittleEndian-Maschine Bytes in der umgekehrten Reihenfolge (“‘1000 1001’ ‘0001 0011′”). Denk darüber nach; Wenn ‘A’ und ‘B’ jeweils acht Bits darstellen, wird die Binärzahl ‘AB’ als ‘BA’ in einer LittleEndian-Maschine gespeichert (googeln Sie ‘Endianness’, wenn Sie wissen müssen, warum). ‘htons()’ ist eine bequeme Funktion, die verwendet wird, um einen gegebenen Short in das BigEndian-Format (‘AB’-Format) umzuwandeln, da dies die ‘Network Byte Order’ ist.

    – Anubis

    8. März 2016 um 6:49 Uhr


  • youtube.com/watch?v=NcaiHcBvDR4 Im letzten Teil dieses Videos erklärt der Typ die htons-Funktion.

    – kryptokht

    21. März 2019 um 12:45 Uhr

Benutzeravatar von xingh1991
xingh1991

das htons() Funktion konvertiert Werte zwischen Host- und Netzwerk-Byte-Reihenfolgen. Es gibt einen Unterschied zwischen Big-Endian und Little-Endian und Netzwerk-Byte-Reihenfolge abhängig von Ihrem Computer und dem verwendeten Netzwerkprotokoll.

Benutzeravatar von Kenpachi Zaraki
Kenpachi Zaraki

Dies geschieht, um die Anordnung der Bytes, die im Netzwerk gesendet werden, beizubehalten (Endianness).

Abhängig von der Architektur Ihres Geräts können Daten im Speicher entweder im Big-Endian-Format oder im Little-Endian-Format angeordnet werden. In Netzwerken nennen wir die Darstellung der Byte-Reihenfolge Netzwerk-Byte-Reihenfolge und in unserem Host heißt sie Host-Byte-Reihenfolge. Die gesamte Netzwerk-Byte-Reihenfolge ist im Big-Endian-Format.

Wenn die Arbeitsspeicher-Computerarchitektur Ihres Hosts im Little-Endian-Format vorliegt, wird die htons() Funktion erforderlich, aber im Falle einer Speicherarchitektur im Big-Endian-Format ist dies nicht erforderlich.

Sie können die Endianness Ihres Computers auch programmgesteuert auf folgende Weise finden:

int x = 1;
if (*(char*)&x) {
    cout << "Little Endian\n";
} else {
    cout << "Big Endian\n";
}

Und dann entscheiden, ob zu verwenden htons() oder nicht. Aber um die obige Zeile zu vermeiden, schreiben wir immer htons() obwohl es keine Änderungen für die Speicherarchitektur auf Big-Endian-Basis vornimmt.

Um die Bedingungen klarzustellen, portno ist ein ganze Zahlund sockaddr ist ein Streaming-Container.

Wenn Sie Daten über das Netzwerk senden, fügen Sie sie durch einen Mechanismus namens in einen Stream ein Serialisierung. Im Zusammenhang mit Netzwerken ist die übliche Regel, Zahlen in Big-Endian-Byte-Reihenfolge anzugeben, dh höherwertige Ziffern eines ganzzahligen Typs kommen zuerst. Wenn das Speicherlayout Ihrer Prozessorarchitektur auch Big Endian ist, geht die Speicherdarstellung einer Ganzzahl einzeln an den Container, ansonsten muss die Byte-Reihenfolge angepasst werden. Und das ist was htons tut: Erstellen eines kurzen int-Werts sin_portso dass das Speicherlayout die Big-Endian-Darstellung der gemeinten Portnummer enthält.

1417120cookie-checkhtons()-Funktion in der Socket-Programmierung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy