Programmation Réseau en C sous Unix
1
Chapitre 1 : Notions de base I. Structure d’adresse :
E p og a atio seau, ous allo s utilise les so kets. C est u o e de o u i atio ui se définit par un port et une adresse.
Elle est ep se t e sous la fo e d u des ipteu de fi hie u e tier).
Les fo tio s pe etta t de a ipule des so kets p e e t e a gu e t u e st u tu e d ad esse de socket.
a) La structure d’adresse de socket IPV4 :
Aussi appel "st u tu e d ad esse de so ket i te et", elle est d fi ie da s <netinet/in.h>.
struct sockaddr_in {
uint8_t sin_len; //taille de la structure sa_family_t sin_family; //famille de la socket in_port_t sin_port; //numéro de port TCP ou UDP struct in_addr sin_addr; //adresse IPv4
char sin_zero[8]; //inutilisé };
Avec
struct in_addr {
in_addr_t s_addr; //adresse IPv4 sur 32 bits };
sin_len : utilisé uniquement avec les sockets de routage.
sin_family : vaut AF_INET pour un socket IPv4.
sin_port : numéro de port sur 16 bits.
sin_addr : adresse IPv4 sur 32 bits.
b) Structure d’adresse de socket générique :
Les fonctions de gestion de socket doivent fonctionner avec toutes les familles de protocoles supportées, donc avec différentes structures de socket.
Programmation Réseau en C sous Unix
2
Problème : o e t fai e pou u u e fo tio a epte des st u tu es diff e tes o e paramètres ?
o on peut utiliser un pointeur void* en ANSI C. Ce qui ne fonctionne pas avec les sockets.
o On utilise une structure générique pouvant contenir toutes les autres
struct sockaddr {
uint8_t sa_lem;
sa_family_t sa_family;
char sa_data[14];
}
Tout appel à u e fo tio de so ket se fe a a e u t a st page de la st u tu e d ad esse de so ket générique.
Grâce au champ sa_family, le compilateur saura où se trouvent les différents champs de la structure.
Exemple :
struct sockaddr_in servaddr;
int sockfd;
: //remplissage servaddr : //initialization sockfd
connect(sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr));
NB :
A a t d utilise une st u tu e d ad esse de so ket, il est préférable de linitialiser à 0. Cela se fait avec un des 2 fonctions suivantes :
#include <strings.h>
void bzero(void* dest, size_t nbytes);
#include <string.h>
void *memset(void* dest, int c, size_t len);
II. Ordre d’octets :
Soit un entier codé sur 16 bits (2 octets). Il y a 2 façons de le stocker en mémoire : Adresses croissantes
Programmation Réseau en C sous Unix
3 Octet de poids fort Octet de poids faible
Octet de poids faible Octet de poids fort
Il a pas de o e su la faço do t so t stockées les valeurs multi-octets en mémoire. Ce qui peut poser problème :
Exemple :
259 en little-endian : poids fort | poids faible 0000 0001|0000 0011 poids faible| poids fort
Lu sur un système en big-endian :
769
Cette différence de stockage est importante en programmation réseau car les protocoles réseaux sp ifie t tous u o d e seau d o tets. Pa e e ple, les p otocoles internet utilisent les big-endian.
Les champs port et adresse des structures de socket doivent être en ordre réseau.
Si l o d e de sto kage de la a hi e est pas le e ue l o d e seau, il faut o e ti les valeurs.
#include <netinet/in.h>
uint16_t htons(uint16_t val);
uint32_t htonl(uint32_t val);
retournent val en ordre réseau sur 16 et 32 bits uint16_t ntohs(uint16_t val);
uint32_t ntohl(uint32_t val);
retournent val en ordre machine sur 16 et 32 bits h : hôte
n : network s : short l : long
III. Conversion d’adresses :
Les adresses IP sont toujours utilisées sous la forme de 32 bits par les fonctions en programmation seau. O , ette fo e est pas utilisa le pa u hu ai . O utilise g ale e t la fo e d i ale pointée X.Y.Z.T.
On a donc besoin de fonctions de conversions entre ces 2 formes.
Ordre little-endian
Ordre big-endian
Programmation Réseau en C sous Unix
4 a)
Fonctions IPv4 seulement :
#include <arpa/inet.h>
int inet_aton(const char *str, struct inaddr *addr);
convertit l’adresse décimal pointée str en adresse sur 32 bits addr (en ordre réseau)
char *inet_ntoa(struct in_addr addr)
convertit l’adresse sur 32 bits addr et retourne la forme décimale pointée.
b) Fonctions IPv4 et IPv6 :
#include <arpa/inet.h>
int inet_pton(in family, char *str, void *addr);
Transforme l’adresse décimale pointée str en adresse sur 32 bits addr.
Family = AF_INET pour IPv4 = AF_INET6 pour IPv6
char *inet_ntop(int family, void *addr, char *str, size_t len);
Convertit addr sur 32 bits en adresse sous forme décimale pointée str.
Family : cf inet_pton
Len : taille de la chaine : IPv4 = 16
IPv6 = 46
Programmation Réseau en C sous Unix
5
Chapitre 2 : les sockets TCP
I. Fonctionnement d’un client et d’un serveur TCP
Nous allo s tous d a o d oi les diff e tes fo tio s essai es à l ta lisse e t, le ai tie et la fi d u e o e io e t e u lie t et un serveur TCP.
Client Serveur
II. La fonction socket :
#include <sys/socket.h>
Int socket (int family, int type, int protocole) Retourne un descripteur de socket
Crée un socket avec le type de protocole de communication désiré.
Socket()
Bind()
listen()
accept()
read()
write()
read()
Socket() Socket()
connect()
write()
read()
close()