【Linux】 Escritura de socket de red informática

prefacio

En el último artículo, aprendimos sobre las capas de redes informáticas y comprendimos que la esencia de la comunicación de la red es la comunicación entre procesos, que se comunica formalmente a través de sockets.

Protocolo TCP y protocolo UDP

El protocolo TCP/UDP es un protocolo que funciona en la capa de transporte, es responsable de la transmisión de datos y proporciona principalmente estrategias de transmisión de datos . TCP y UDP son dos estrategias de transmisión de datos diferentes.

  • TCP (Protocolo de control de transmisión)

    • orientado a la conexión
    • Transmisión confiable
    • flujo de bytes orientado
  • UDP (Protocolo de datagramas de usuario)

    • sin conexión
    • Transmisión poco confiable
    • orientado a datagramas

Tenga en cuenta que la confiabilidad y falta de confiabilidad mencionadas aquí no significan que TCP sea mejor que UDP, sino sus características de transmisión, lo discutiremos en detalle al explicar el protocolo específico.
Dado que el protocolo UDP no está orientado a la conexión, la simplicidad es su gran ventaja. Hoy aprenderemos primero en detalle sobre los sockets UDP simples.

orden de bytes de red

Al aprender el lenguaje C, especificamos que los datos de varios bytes en la memoria se dividen en endian grande y pequeño en relación con la dirección, y el flujo de red también se divide en endian grande y pequeño.

1. El host emisor generalmente envía los datos en el búfer de envío de menor a mayor
2. La oración principal de recepción generalmente guarda los datos recibidos en orden de menor a mayor 3.
Por lo tanto, la dirección del flujo de datos de la red se especifica como : primero Los datos enviados son la dirección baja y los datos enviados después son la dirección alta
4. El protocolo TCP/IP estipula que el flujo de datos de la red debe utilizar el orden de bytes big endian, es decir: dirección baja byte alto

interfaz:

#include <arpa/inet.h>

uint16_t htons(uint16_t hostshort)
uint16_t ntohs(uint16_t netshort)

interfaz de enchufe

La interfaz de socket es como la llamada al sistema que usamos antes, que es una interfaz a nivel de sistema operativo.

estructura sockaddr

1. Los tipos de direcciones de ipv4 e ipv6 se definen como AF_INET y AF_INET6 respectivamente, que se encuentran en netinet/in.h. Cuando utilice socketAPI, primero puede convertir la estructura sockaddr_in correspondiente a sockaddr. Dentro de la interfaz, se basará en el tipo de dirección de 16 bits Realice diferentes tipos de operaciones, que es una manifestación temprana del polimorfismo en el lenguaje C.

2. Los sockets no solo pueden comunicarse a través de la red: debido a la existencia de conversión sockaddr + tipo de dirección de 16 bits, socketAPI también admite la comunicación entre procesos.
Insertar descripción de la imagen aquí

1.Crear socket cs

int socket(int domain, int type,int protocol)

parámetro:

  • dominio:ipv4 está escrito como AF_INET
  • tipo: udp es: SOCK_DGRAM; tcp es: SOCK_STREAM
  • protocolo: establecido en 0 por defecto

2. Vincular los números de puerto

int bind(int socket,const struct sockaddr* address,socklen_t address_len);
实例:
struct sockaddr_in local;

local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = INADDR_ANY;

Por cierto, los servicios en la nube no nos permiten vincularnos a una dirección IP específica, por lo que usamos INADDR_ANY para vincular cualquier IP de este host.

3. Escuche los enchufes

int listen(int socket, int backlog);

parámetro:

  • socket: el socket para escuchar
  • Atrasos: cola de espera más larga

4.Aceptar solicitudes

int accept(int socket, struct sockaddr* address,socklen* address_len);

parámetro:

  • enchufe: enchufe
  • dirección: se utiliza para almacenar la información de la dirección del cliente.
  • Address_len: parámetros de entrada y salida. Como entrada, especifica la longitud del buffer apuntado por la dirección. Como salida, se establecerá en la longitud de la dirección real. Por ejemplo, hay 10 bytes en la entrada, pero solo 8 En realidad, las palabras son pasadas por el cliente, este parámetro se modificará a ocho bytes.

5.Establecer conexión c

int connect(int sockfd,const struct sockaddr* addr,socklen_t addrlen);

parámetro:

  • sockfd: descriptor de archivo creado por el cliente
  • addr: se utiliza para especificar la información de la dirección en el lado del servidor
  • addrlen: el tamaño real de addr

función de traducción de direcciones

Estamos acostumbrados a usar notación decimal con puntos para registrar direcciones IP, como 101.34.23.11, pero la red usa 32 bits para registrar direcciones IP, por lo que necesitamos convertir la dirección IP de estilo decimal con puntos en una dirección de red.

Convertir cadena a in_addr

#include <arpa/inet.h>

int inet_aton(const char* strptr,struct in_addr* addrptr);

struct in_addr 
{
    
    
    in_addr_t s_addr; // 存储32位的IPv4地址
};

parámetro:

  • strptr: cadena ip a convertir
  • addrptr: accede a la dirección de 32 bits convertida

valor de retorno:

  • Devuelve 1 si la conversión se realiza correctamente y 0 si la conversión falla.

int inet_pton(int family,const char* strptr,void* addrptr);

parámetro:

  • familia: familia de protocolos que se va a convertir
  • strptr: cadena IP a convertir (compatible con 4 y 6)
  • addrptr: el búfer colocado después de la conversión

valor de retorno:

  • Devuelve 1 con éxito
  • Devuelve 0 en caso de error
  • Si no es válido, se devuelve -1 y se establece errno.

in_addr_t inet_addr(const char* strptr);

parámetro:

  • strptr: cadena ip a convertir

valor de retorno:

  • Devuelve con éxito la dirección IP de 32 bits
  • Devuelve INADDR_NONE en caso de error

in_addr a cadena

char* inet_ntoa(struct in_addr inaddr);

parámetro:

  • inaddr: convierte la dirección IP de 32 bits a decimal con puntos

int inet_pton(int family,const void* addrptr,char* strptr);

parámetro:

  • familia: familia de protocolo
  • addrptr: puntero para almacenar la cadena ip
  • strptr: buffer para almacenar el binario convertido

valor de retorno:

  • Devuelve 1 en caso de éxito, -1 en caso de error

recibir desde y enviar a

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                struct sockaddr *src_addr, socklen_t *addrlen);

parámetro:

  • sockfd: el socket para recibir datos
  • buf: puntero de búfer, que apunta a almacenar los datos recibidos
  • len: tamaño del buffer, bytes máximos que se esperan recibir
  • flags: Banderas para recibir datos, que pueden ser 0 u opciones de recepción específicas
  • src_addr: un puntero de estructura que almacena la dirección del socket del remitente, que puede ser NULL
  • addrlen: especifica el tamaño de la estructura de la otra parte

Nota: Los dos últimos parámetros no están incluidos en recv porque TCP está orientado a la conexión y no es necesario leer los dos últimos parámetros.


#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
              const struct sockaddr *dest_addr, socklen_t addrlen);

parámetro:

  • sockfd: descriptor de socket
  • buf: datos a enviar
  • len: tamaño enviado
  • banderas: método de envío
  • dest_addr: información del socket del host de destino
  • addrlen: tamaño

De manera similar, enviar no requiere los dos últimos parámetros.

Supongo que te gusta

Origin blog.csdn.net/m0_73209194/article/details/132095048
Recomendado
Clasificación