2012-02-16 16 views
14

Puedo ver por qué es útil para convertir sockaddr en sockaddr_in, pero no entiendo cómo es posible. Por lo que he leído, son del mismo tamaño y sockaddr_in se agrega con sin_zero para que sea del mismo tamaño. Me gustaría saber cómo sabe el compilador dónde obtener la información de sockaddr_in si se presenta de forma diferente a sockaddr.Por qué podemos lanzar sockaddr a sockaddr_in

Respuesta

16

Es posible porque normalmente lanza los punteros, no las estructuras en sí. Hace lo que en lenguaje natural significa "por favor, trate este puntero a un socket structure como un puntero a un internet socket structure en su lugar". El compilador no tiene problemas para volver a interpretar el puntero.

Esta es la descripción más detallada tomada a partir de los comentarios:

A sockaddr es de 16 bytes de tamaño - los primeros dos bytes son la sa_family, y los 14 bytes restantes son el sa_data que son datos arbitrarios. Un sockaddr_in también tiene 16 bytes de tamaño: los primeros 2 bytes son sin_family (siempre AF_INET), los siguientes 2 bytes son sin_port, los siguientes 4 bytes son sin_addr (dirección IP) y los últimos 8 bytes son sin_zero que no se utiliza en IPv4 y se proporciona solo para garantizar 16 bytes. De esta forma, puede mirar primero al sockaddr.sa_family, y si es AF_INET, entonces interprete el sockaddr completo como .

A sockaddr_in no se almacena dentro del campo sockaddr.sa_data. El sockaddr completo es el sockaddr_in completo (cuando sockaddr.sa_family es AF_INET, es decir). Si se toma un puntero sockaddr* y echarlo a un puntero sockaddr_in*, entonces:

  • sockaddr.sa_family es sockaddr_in.sin_family
  • bytes 0-1 de sockaddr.sa_data son sockaddr_in.sin_port
  • bytes 2-5 son sockaddr_in.sin_addr
  • bytes 6 -13 son sockaddr_in.sin_zero.
+0

Parece extraño porque la variable que se supone que almacena la dirección en sockaddr es sa_data que es char [14], pero sockaddr_in usa un corto sin signo. Supongo que el compilador leerá el primer número corto sin firmar de bytes del char [14] y hará que la dirección, y el resto de char [14] sean los datos que se enviarán? Además, si agrego los tamaños de las dos estructuras, no parecen ser del mismo tamaño. sin_zero parece demasiado grande. ¡Solo estoy tratando de entender qué está pasando aquí! –

+11

Un 'sockaddr' tiene 16 bytes de tamaño; los primeros dos bytes son' sa_family', y los 14 bytes restantes son 'sa_data', que son datos arbitrarios. Un 'sockaddr_in' también tiene 16 bytes de tamaño: los primeros 2 bytes son' sin_family' (siempre 'AF_INET'), los siguientes 2 bytes son' sin_port', los siguientes 4 bytes son 'sin_addr' (dirección IP) , y los últimos 8 bytes son 'sin_zero' que no se utilizan en IPv4 y se proporcionan solo para garantizar 16 bytes. De esta forma, puedes mirar 'sockaddr.sa_family' primero, y si es' AF_INET' luego interpretar todo el 'sockaddr' como' sockaddr_in'. –

+6

Un 'sockaddr_in' no está almacenado dentro del campo' sockaddr.sa_data'. Toda la 'sockaddr' ** es ** la totalidad de' sockaddr_in' (cuando 'sockaddr.sa_family' es' AF_INET', eso es). Si toma un puntero 'sockaddr *' y lo convierte en un puntero 'sockaddr_in *', 'sockaddr.sa_family' es' sockaddr_in.sin_family', los bytes 0-1 de 'sockaddr.sa_data' son' sockaddr_in.sin_port', bytes 2-5 son 'sockaddr_in.sin_addr', y los bytes 6-13 son' sockaddr_in.sin_zero'. –

Cuestiones relacionadas