2013-10-06 24 views
25

Jestem nowy w programowaniu gniazd i próbuję zrozumieć działanie htons(). Czytałem kilka tutoriali w Internecie, takich jak na przykład this i this. Ale nie mogłem dokładnie zrozumieć, co dokładnie robię. Próbowałem następujący kod:Funkcja htons() w programowaniu gniazd

#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; 
} 

Wartość sin_port został pokazany jako 35091 podczas debugowania i nie rozumiem jak portno zmieniło od 5001 do 35091. Czy mógłby ktoś wyjaśnić przyczynę tej zmiany wartości?

+1

Jakie jest twoje zrozumienie tego, co robi 'htons()'? Czytałeś to: http://en.wikipedia.org/wiki/Endianness. –

+0

Zgodnie z podręcznikiem systemu Linux Funkcja 'htons()' konwertuje niepodpisaną krótką liczbę całkowitą hostshort z kolejności bajtów hosta na kolejność bajtów sieciowych. – Shushant

+0

Znam dużą Endianne i małą Endianne, ale nie znam operacji htons() dokładnie !!! – User123422

Odpowiedz

20

htons jest host-to-network short

Oznacza to, że działa na 16-bitowych liczb całkowitych krótkich. tj. 2 bajty.

Ta funkcja zamienia endianię skrótu.

Twój numer zaczyna się na:

0001 0011 1000 1001 = 5001

Gdy kolejność bajtów jest zmieniona, to zamienia dwa bajty:

1000 1001 0001 0011 = 35091

+0

oznacza, że ​​0001 0011 to bajty hosta, a 1000 1001 to sieci? – User123422

+1

@ User123422 Nie, nie masz racji. Nawet jeśli binarna forma 5001 to "0001 0011", "1000 1001" ", to podczas przechowywania jej w maszynie LittleEndian przechowuje bajty w odwrotnej kolejności (" '1000 1001' '0001 0011 ""). Pomyśl o tym; jeśli "A" i "B" reprezentują osiem bitów każda, liczba binarna "AB" będzie przechowywana jako "BA" w maszynie LittleEndian (google "Endianness", jeśli musisz wiedzieć dlaczego). "htons()" to wygodna funkcja używana do konwersji dowolnego skrótu do formatu BigEndian (format "AB"), ponieważ jest to "Network Byte Order". – Anubis

3

funkcja htons() przeliczać pomiędzy hostem a bajt sieci święcenia. Istnieje różnica między big-endian i little-endian i kolejnością bajtów sieci w zależności od używanego komputera i protokołu sieciowego.

67

Ma to związek z kolejnością zapisywania bajtów w pamięci. Liczba dziesiętna 5001 to 0x1389 w systemie szesnastkowym, więc uwzględnione bajty to: 0x13 i 0x89. Wiele urządzeń zapisuje numery w formacie little-endian, co oznacza, że ​​najmniej znaczący bajt jest najważniejszy. Tak więc w tym konkretnym przypadku oznacza to, że w pamięci numer 5001 zostaną zapisane jako

0x89 0x13 

Funkcja htons() zapewnia, że ​​numery są przechowywane w pamięci w sieciowej kolejności bajtów, czyli z najbardziej znaczący bajt pierwszy. Będzie zatem zamienić bajtów składających się na liczbę tak, że w pamięci bajtów będą przechowywane w kolejności

0x13 0x89 

Na ostrokońcej maszyny, numer z zamienionych bajtów jest 0x8913 w systemie szesnastkowym, który jest 35091 w zapisie dziesiętnym. Zauważ, że jeśli pracujesz na maszynie Big-Endian, funkcja htons() nie będzie wymagała żadnej zamiany, ponieważ ta liczba będzie już poprawnie zapisana w pamięci.

Przyczyną tego zamiany jest używanie używanych protokołów sieciowych, które wymagają, aby przesyłane pakiety używały kolejności bajtów sieciowych.

Powiązane problemy