how - función htons() en la programación de socket
socket tcp in c (3)
La función htons()
convierte valores entre órdenes de bytes del host y de la red. Existe una diferencia entre big-endian y little-endian y orden de bytes de red dependiendo de su máquina y protocolo de red en uso.
Soy nuevo en la programación de socket y estoy tratando de entender el funcionamiento de htons()
. He leído algunos tutoriales en Internet como this y this por ejemplo. Pero no pude entender lo que htons()
hace exactamente. Probé el siguiente código:
#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;
}
El valor de sin_port
se mostró como 35091
durante la depuración y no entiendo cómo portno
cambió de 5001
a 35091
. ¿Podría alguien explicar el motivo de ese cambio de valor, por favor?
Tiene que ver con el orden en que los bytes se almacenan en la memoria. El número decimal 5001
es 0x1389
en hexadecimal, por lo que los bytes implicados son 0x13
y 0x89
. Muchos dispositivos almacenan números en formato little-endian , lo que significa que el byte menos significativo es lo primero. Entonces, en este ejemplo particular, significa que en la memoria el número 5001
se almacenará como
0x89 0x13
La función htons()
se asegura de que los números se almacenen en la memoria en orden de bytes de red, que es con el byte más significativo primero. Por lo tanto, intercambiará los bytes que componen el número para que en la memoria los bytes se almacenarán en el orden
0x13 0x89
En una máquina little-endian , el número con los bytes intercambiados es 0x8913
en hexadecimal, que es 35091
en notación decimal. Tenga en cuenta que si estuviera trabajando en una máquina big-endian , la función htons()
no necesitaría hacer ningún intercambio ya que el número ya estaría almacenado en la memoria de la manera correcta.
El motivo subyacente de todo este intercambio tiene que ver con los protocolos de red en uso, que requieren que los paquetes transmitidos utilicen el orden de bytes de red.
htons
es htons
host-to-network short
Esto significa que funciona en enteros cortos de 16 bits. es decir, 2 bytes.
Esta función intercambia la endianidad de un corto.
Su número comienza en:
0001 0011 1000 1001 = 5001
Cuando se cambia la endianidad, intercambia los dos bytes:
1000 1001 0001 0011 = 35091