Conceptos relacionados con el socket de programación de red

Orden de bytes

Para comprender la programación de redes, debe comprender el orden de almacenamiento de bytes en la comunicación por computadora.

Concepto endian

Considerando una máquina de 32 bits, el acumulador de CPU puede cargar 4 bytes a la vez. El orden de los 4 bytes en la memoria afecta el valor entero cargado por el acumulador.
La endianidad se divide en Big-Endian y Little-Endian. El remitente siempre tiene que convertir los datos al orden de bytes big-endian y enviarlos

  • Orden de bytes big-endian: se refiere al byte de orden superior del entero almacenado en la dirección baja de la memoria, también conocido como orden de bytes de red.
  • Orden de bytes Little-endian: el byte de orden superior del entero se almacena en la dirección superior de la memoria, que es la que utilizan principalmente las PC modernas.

Suponiendo que la dirección del aumento de la memoria es de izquierda a derecha, el formato de almacenamiento de 12345678 en la memoria es el siguiente

  • El almacenamiento en orden de bytes big-endian es 0x12 0x34 0x56 0x78, 12 es el bit alto del número, almacenado en el bit bajo de la dirección de memoria
  • El almacenamiento en orden de bytes little-endian es 0x78 0x56 0x34 0x12, 12 es el bit alto del número, almacenado en el bit alto de la dirección de memoria

Función de conversión endian

La función de conversión de orden de bytes está encapsulada en BSD Socket, el archivo de encabezado es #include <arpa / inet.h>

  1. Puerto de conversión
  • uint16_t htons (uint16_t hostshort); // orden de bytes del host-orden de bytes de la red
  • uint16_t ntohs (uint16_t netshort); // orden de bytes de red-orden de bytes de host
  1. Convertir IP
  • uint32_t htonl (uint32_t hostlong); // orden de bytes del host-orden de bytes de la red
  • uint32_t ntohk (uint32_t netlong); // Orden de bytes de red-orden de bytes de host

entre ellos

  • h-host host, orden de bytes del host
  • a-que convertir en
  • orden de bytes de la red n-network
  • s - corto sin firmar corto
  • l - int largo sin firmar

Introducción al zócalo

El socket se utiliza para la comunicación entre procesos entre diferentes hosts. El
socket contiene la dirección IP y el puerto. La
comunicación del socket se divide en lado del servidor y lado del cliente.

Socket socket es una abstracción del punto de interrupción de la comunicación bidireccional entre procesos de aplicación en diferentes hosts de la red. El socket es un extremo de la comunicación del proceso en la red, que proporciona un mecanismo para que los procesos de la capa de aplicación intercambien datos utilizando protocolos de red.

El zócalo se puede considerar como el punto final de cada conexión de comunicación cuando se comunican dos aplicaciones de red. Este es un concepto lógico. Es una API para la comunicación entre procesos en un entorno de red, y también es un punto final de comunicación que se puede nombrar y direccionar.Cada socket en uso tiene su tipo y un proceso conectado a él.

En el entorno Linux, los sockets se utilizan para representar tipos de archivos especiales para la comunicación de red entre procesos. La esencia es un pseudoarchivo formado por el kernel con la ayuda de un búfer. Se puede hacer referencia a ellos con descriptores de archivos.

dirección de socket

La dirección del socket es en realidad una estructura que encapsula información como el número de puerto y la IP

La dirección de socket incluye la dirección de socket general y la dirección de socket dedicada

Dirección de enchufe universal

La dirección del zócalo en la interfaz de programación de la red del zócalo es la estructura sockaddr, que se define de la siguiente manera

#include <bits/socket.h>
struct sockaddr {
    
    
    sa_family_t sa_family;
    char sa_data[14];
};
typedef unsigned short int sa_family_t;

El miembro sa_family es una variable del tipo de familia de direcciones (sa_family_t). El tipo de familia de direcciones generalmente corresponde al tipo de familia de protocolo. La
familia de protocolo común (también llamada dominio) y la familia de direcciones correspondiente son las siguientes:
Inserte la descripción de la imagen aquí
Las macros PF_ * y AF_ * se definen en el archivo de encabezado bits / socket.h, y el último tiene exactamente el mismo valor que el anterior, por lo que el dos suelen estar mezclados
.
El miembro sa_data se utiliza para almacenar el valor de la dirección del socket. Sin embargo, los valores de dirección de diferentes familias de protocolos tienen diferentes significados y longitudes, como se
muestra a continuación : El
Inserte la descripción de la imagen aquí
sa_data de 14 bytes no puede contener los valores de dirección de la mayoría de las familias de protocolos. Por lo tanto, Linux define la siguiente nueva
estructura general de direcciones de socket.Esta estructura no solo proporciona suficiente espacio para almacenar valores de dirección, sino que también está alineada con la memoria.

#include <bits/socket.h>
struct sockaddr_storage
{
    
    
    sa_family_t sa_family;
    unsigned long int __ss_align;
    char __ss_padding[ 128 - sizeof(__ss_align) ];
};
typedef unsigned short int sa_family_t;

Dirección de socket dedicada

Muchas funciones de programación de red nacieron antes que el protocolo IPv4. En ese momento, se usaba la estructura struct sockaddr. Para compatibilidad hacia adelante, sockaddr ahora degenera en un rol (void *), pasando una dirección a la función. En cuanto a la función es sockaddr_in o sockaddr_in6 está determinado por la familia de direcciones, y luego la función se ve obligada a convertir el tipo al tipo de dirección requerido.

Inserte la descripción de la imagen aquí
La estructura general del enchufe no es fácil de usar. Es necesario realizar tediosas operaciones de bits al configurar y obtener la dirección IP y el número de puerto. Por lo tanto, Linux proporciona una estructura de socket dedicada para cada familia de protocolos.

La familia de protocolos de dominio local de UNIX utiliza la siguiente estructura de dirección de socket dedicada:

#include <sys/un.h>
struct sockaddr_un
{
    
    
    sa_family_t sin_family;
    char sun_path[108];
};

La familia de protocolos TCP / IP tiene dos estructuras de direcciones de socket dedicadas, sockaddr_in y sockaddr_in6, que se utilizan para IPv4 e IPv6 respectivamente:

#include <netinet/in.h>
struct sockaddr_in
{
    
    
    sa_family_t sin_family; /* __SOCKADDR_COMMON(sin_) */
    in_port_t sin_port; /* Port number. */
    struct in_addr sin_addr; /* Internet address. */
    /* Pad to size of `struct sockaddr'. */
    unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE -
    sizeof (in_port_t) - sizeof (struct in_addr)];
};
struct in_addr
{
    
    
    in_addr_t s_addr;
};
struct sockaddr_in6
{
    
    
    sa_family_t sin6_family;
    in_port_t sin6_port; /* Transport layer port # */
    uint32_t sin6_flowinfo; /* IPv6 flow information */
    struct in6_addr sin6_addr; /* IPv6 address */
    uint32_t sin6_scope_id; /* IPv6 scope-id */
};
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))

Cabe resaltar que:

  1. Los números de puerto en estas estructuras de socket dedicadas se expresan en orden de bytes de red.
  2. Todas las variables del tipo de dirección de socket dedicada (y sockaddr_storage) deben convertirse al tipo de dirección de socket universal sockaddr (coerción directa) durante el uso real, porque el tipo de parámetro de dirección utilizado por todas las API de programación de socket es sockaddr.

Supongo que te gusta

Origin blog.csdn.net/MinutkiBegut/article/details/114265869
Recomendado
Clasificación