Programmation réseau (basique)

Mise en garde: C'est un mémo personnel. Nous ne garantissons pas que le contenu est correct. De plus, si vous ne connaissez pas le système d'utilisation ou le langage C, veuillez ne pas l'imiter. C'est dangereux. (Pendant l'édition)

Basiques

Programmation réseau

La communication inter-processus peut être effectuée sur le même ordinateur tel qu'un tube (tube (2)) ou FIFO (tube nommé). En principe, cette communication inter-processus s'effectue sur un ordinateur différent, sur un réseau auquel vous n'appartenez pas. Cela signifie ce qui est fait conformément à l'accord de communication.

Attention à l'architecture

Alignement de la structure, ordre des octets et comment le bus d'adresse pointe vers une adresse La largeur du bus etc. diffère en fonction de l'architecture utilisée. Le langage C confie aux utilisateurs du langage C la tâche de faire la différence. Veillez à ne pas vous fier à l'ordinateur lorsque vous communiquez avec différents ordinateurs du réseau. Par exemple, sur un processeur de type RISC, l'accès à une adresse impaire peut entraîner une erreur de bus.

Appel système

La programmation réseau utilise des appels système (uapi) pour créer des applications. Dans les applications utilisateur, le noyau fonctionne en mode utilisateur et utilise la mémoire virtuelle. Le système d'exploitation gère directement les modules réseau. Cela se fait en mode noyau (mode privilégié).

Les applications réseau utilisent une interface appelée sockets. Les sockets peuvent être traités comme des fichiers spéciaux. Exécutez sokect (2) pour créer une socket.

Les sockets sont toujours des fichiers. Par conséquent, des fonctions d'entrée / sortie binaires telles que read (2) et write (2) peuvent également être utilisées.

Le socket créé peut être adressé par bind (2). De plus, comme les sockets sont un type de fichier, ils sont gérés par le numéro d'inode.

Le module réseau contenant la prise dispose d'un tampon pour stocker les données Mettez le paquet en file d'attente. Pour demander au système d'exploitation d'envoyer des données Émettez send (2) dans l'application d'envoi. (C'est une demande, pas une garantie) S'il y a de l'espace libre dans le tampon, il sera stocké dans la file d'attente.

Les données peuvent être obtenues en émettant recv (2) dans l'application réceptrice. Demandez la récupération des données du tampon. Le programme est bloqué si les données reçues n'existent pas dans la file d'attente. Notez que recv (2) récupère les données du tampon même si l'application n'est pas en cours d'exécution. Notez que s'il ne se termine pas normalement, les données seront récupérées indéfiniment.

Les interruptions sont utilisées par le NIC pour envoyer et recevoir des données. Ceci est pris en charge par le noyau, En langage C, les signaux abstraits pour les utilisateurs sont préparés.

Redondance

Lorsqu'il y a des demandes de plusieurs clients vers des applications réseau L'application peut dépasser la puissance de traitement. Dans ce cas, multi-processus, multi-thread, select (2), etc. sont utilisés.

Gérer les erreurs

connect (2) est utilisé pour identifier le partenaire de communication au niveau de l'application. Si le processus de transmission / réception de données ne se termine pas normalement pendant que la connexion est établie, que ce soit TCP ou UDP. S'il n'est pas modifié, le traitement peut être bloqué pour toujours. S'il est mauvais, même l'entrée de clé ne sera pas acceptée.

Par conséquent, il expire avec alerm (2), setitimer (2), etc. Gestion appropriée du signal avec sigaction (2) etc.

En-tête de protocole

De nombreux protocoles sont représentés par des structures en langage C. Beaucoup de ces détails se trouvent dans les répertoires suivants:

/usr/include/net/* /usr/include/netinet/*

TCP/IP

Communication de type DGRAM et communication de type STREAM

Domaine UNIX et domaine INET

Les données

En TCP / IP, la communication est effectuée par échange de paquets.

Un paquet se compose d'un en-tête et d'une charge utile.

entête

L'en-tête contient des informations sur l'adresse de destination, l'adresse source, la charge utile, etc.

charge utile

La charge utile correspond aux données avec lesquelles vous souhaitez communiquer

message

Une application de communication sera créée sur l'OS et les données échangées entre ces applications sont appelées message.

Type de données

Les types de données dans les en-têtes répertoriés ci-dessous garantissent la taille en bits. Ceci est également fourni pour les systèmes d'exploitation compatibles POSIX.

/usr/include/stdint.h

<stdint.h> <inttypes.h> (C99)

Exemple:


uint32_t /*Type int 32 bits non signé*/

La manière dont il est défini dépend du système. Voir l'en-tête directement pour plus de détails.

Ordre des octets du réseau

En-têtes de protocole TCP / IP sur le réseau Unifiez les messages d'application aux big endians. Les fonctions suivantes peuvent être utilisées pour la conversion endian.


#include <arpa/inet.h> /*Selon le système<net/inet.h> */

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);


#include <stdio.h>
#include <arpa/inet.h>

int main(void)
{
    uint32_t s = 0xff;

    /* host to network endian */
    uint32_t r = htonl(s);

    printf("%#0.8x\n", r);
    printf("%#0.8x\n", s);
    return 0;
}

Exemple de résultat


0xff000000
0x000000ff

Résolution de nom de l'adresse IP et du nom de domaine

1 . Utilisez le fichier / etc / hosts


#include <netdb.h>
struct hostent *gethostbyname(const char *name);

#include <sys/socket.h>
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);

2 . Utiliser DNS


#include <sys/socket.h>
void sethostent(int stayopen);
void endhostent(void);

Lors de la résolution du nom avec le serveur DNS, enregistrez l'adresse sur le serveur DNS dans /etc/resolv.conf à l'avance.

Entrée de protocole

/etc/protocols

#include <netdb.h>

struct protoent *getprotoent(void);
struct protoent *getprotobyname(const char *name);
struct protoent *getprotobynumber(int proto);

Entrée de service

/etc/services


#include <netdb.h>

struct servent *getservent(void);
struct servent *getservbyname(const char *name, const char *proto);
struct servent *getservbyport(int port, const char *proto);

Recommended Posts

Programmation réseau (basique)
Paramètres de base de CentOS 7 après les paramètres réseau
réseau
Programmation réseau avec Python Scapy
Numpy [basique]
Écriture de base de divers langages de programmation (auto-mémo)
Programmation Feces Gorua
Commandes de base
Évaluation des performances de base du langage de programmation
Programmation graphique
Réseau relationnel
Enregistrement de l'examen de base de la certification d'ingénieur Python3 pour débutant en programmation