Функция htons() в программировании сокетов

Я новичок в программировании сокетов, и я пытаюсь понять работу htons(). Я читал несколько руководств в Интернете, как это, и это, например. Но я не мог понять, что htons() делает htons(). Я попробовал следующий код:

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

Значение sin_port было показано как 35091 при отладке, и я не понимаю, как portno изменилось с 5001 до 35091. Может ли кто-нибудь объяснить причину этого изменения в стоимости, пожалуйста?

Ответ 1

Он связан с порядком, в котором байты хранятся в памяти. Десятичное число 5001 равно 0x1389 в шестнадцатеричном виде, поэтому задействованные байты - 0x13 и 0x89. Многие устройства хранят номера в формате little-endian, что означает, что младший байт приходит первым. Таким образом, в этом конкретном примере это означает, что в памяти число 5001 будет сохранено как

0x89 0x13

Функция htons() гарантирует, что числа сохраняются в памяти в порядке htons() в сети, который сначала содержит старший байт. Поэтому он будет менять байты, составляющие номер, так что в памяти байты будут храниться в порядке

0x13 0x89

На машине с маленькими байтами число с байтами с 0x8913 составляет 0x8913 в шестнадцатеричном формате, что составляет 35091 в десятичной системе. Обратите внимание, что если вы работали над машиной htons() функции htons() не нужно было бы менять, поскольку номер уже был бы правильно сохранен в памяти.

Основная причина всего этого обмена заключается в использовании используемых сетевых протоколов, которые требуют, чтобы переданные пакеты использовали сетевой байтовый порядок.

Ответ 2

htons является host-to-network short

Это означает, что он работает с 16-битными короткими целыми числами. т.е. 2 байта.

Эта функция меняет континент короткого замыкания.

Ваш номер начинается с:

0001 0011 1000 1001 = 5001

Когда значение endianness изменяется, оно меняет местами два байта:

1000 1001 0001 0011 = 35091

Ответ 3

htons() преобразует значения между хост-и сетевыми порядками байтов. Существует различие между порядком бай-инов и малым порядком и сетевым байтом в зависимости от используемого вами протокола машины и сети.