Функция 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()
преобразует значения между хост-и сетевыми порядками байтов. Существует различие между порядком бай-инов и малым порядком и сетевым байтом в зависимости от используемого вами протокола машины и сети.