« C socket » : différence entre les versions
De The Linux Craftsman
Autres actions
Page créée avec « = Introduction = {| |- || Les sockets permettent de connecter deux programmes qui s'exécutent sur deux machines différentes. Cette connexion se fait à travers le résea... » |
|||
| Ligne 12 : | Ligne 12 : | ||
|} | |} | ||
= Utilisation = | = Utilisation = | ||
== Côté serveur == | |||
Tout d'abord il faut créer l'objet socket: | Tout d'abord il faut créer l'objet socket: | ||
<source lang="c"> | <source lang="c"> | ||
| Ligne 25 : | Ligne 26 : | ||
**SOCK_RAW: socket à l'état brut (bas niveau) | **SOCK_RAW: socket à l'état brut (bas niveau) | ||
*protocol → valeur du champ ''protocol'' de l'entête de niveau 3 (généralement ''0'') | *protocol → valeur du champ ''protocol'' de l'entête de niveau 3 (généralement ''0'') | ||
*la valeur de retour est le fichier descripteur de la socket | *la valeur de retour est le fichier descripteur de la socket ou ''-1'' en cas d'erreur (''errno'' est positionné) | ||
Une fois le descripteur de socket créé, il est possible de le configurer: | |||
<source lang="c"> | <source lang="c"> | ||
#include <sys/socket.h> | #include <sys/socket.h> | ||
| Ligne 32 : | Ligne 36 : | ||
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) | int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) | ||
</source> | </source> | ||
* sockfd → le fichier descripteur de la socket; | |||
* level → niveau d'application de l'option (SOL_SOCKET, TCP, UDP, ...); | |||
* optname → le nom de l'option (''SO_REUSEADDR'', ''SO_REUSEPORT'', ''SO_KEEPALIVE'', ...) | |||
* optval, optlen → utilisé pour accéder aux options de la socket; | |||
* le code retour varie entre ''0'' et ''-1'' en cas d'erreur (''errno'' est positionné) | |||
Il existe plusieurs options de socket, les plus utilisées étant : | |||
* ''SO_REUSEADDR'' → permet de réutiliser l'adresse de la socket tout de suite même si cette dernière est dans l'état ''wait''; | |||
* ''SO_REUSEPORT'' → permet de réutiliser le port de la socket tout de suite même si cette dernière est dans l'état ''wait''; | |||
* ''SO_KEEPALIVE'' → envoie des informations périodiquement pour tester si l'extrémité du tunnel est toujours présente; | |||
Il faut maintenant attacher la socket à un port Internet et une adresse IP: | |||
<source lang="c"> | <source lang="c"> | ||
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) | int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) | ||
</source> | </source> | ||
* sockfd → le fichier descripteur de la socket; | |||
* addr → une structure symbolisant l'adresse | |||
<source lang="c"> | |||
struct sockaddr_in { | |||
short sin_family; // e.g: AF_INET | |||
unsigned short sin_port; // e.g: htons(3490) | |||
struct in_addr sin_addr; // détaillé ci-dessous | |||
char sin_zero[8]; // '0' habituellement | |||
}; | |||
struct in_addr { | |||
unsigned long s_addr; // initialiser avec inet_aton() | |||
}; | |||
</source> | |||
* addrlen → la taille de l'objet addr; | |||
* le code retour varie entre ''0'' et ''-1'' en cas d'erreur (''errno'' est positionné) | |||
On peut maintenant passer la socket en état d'écoute, elle est prête à recevoir des connexions: | |||
<source lang="c"> | <source lang="c"> | ||
int listen(int sockfd, int backlog) | int listen(int sockfd, int backlog) | ||
</source> | </source> | ||
* sockfd → le fichier descripteur de la socket; | |||
* backlog → taille maximum de la file d'attente de la socket après laquelle le système répond avec ''ECONNREFUSED''; | |||
* le code retour varie entre ''0'' et ''-1'' en cas d'erreur (''errno'' est positionné) | |||
On peut maintenant attendre une connexion: | |||
<source lang="c"> | <source lang="c"> | ||
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); | int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); | ||
</source> | </source> | ||
* sockfd → le fichier descripteur de la socket; | |||
* addr → l'adresse du client; | |||
* addrlen → la taille de la structure addr; | |||
* le code retour varie entre un entier positif qui correspond au descripteur de la socket cliente et ''-1'' en cas d'erreur (''errno'' est positionné) | |||
== Côté client == | |||
Après avoir créé la socket avec ''socket'' on peut se connecter à la partie serveur: | |||
<source lang="c"> | <source lang="c"> | ||
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); | int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); | ||
</source> | </source> | ||
* sockfd → le fichier descripteur de la socket; | |||
* addr → une structure symbolisant l'adresse (cf. ci-dessus) | |||
* addrlen → la taille de l'objet addr; | |||
* le code retour varie entre ''0'' et ''-1'' en cas d'erreur (''errno'' est positionné) | |||
= Exemple = | |||
== Côté serveur == | |||
== Côté client == | |||
Version du 26 octobre 2018 à 11:23
Introduction
Utilisation
Côté serveur
Tout d'abord il faut créer l'objet socket:
#include <sys/socket.h> #include <netinet/in.h> int socket(int domain, int type, int protocol)
- domain → integer, communication domain e.g., AF_INET (IPv4 protocol) , AF_INET6 (IPv6 protocol)
- type → type de communication
- SOCK_STREAM: TCP
- SOCK_DGRAM: UDP
- SOCK_RAW: socket à l'état brut (bas niveau)
- protocol → valeur du champ protocol de l'entête de niveau 3 (généralement 0)
- la valeur de retour est le fichier descripteur de la socket ou -1 en cas d'erreur (errno est positionné)
Une fois le descripteur de socket créé, il est possible de le configurer:
#include <sys/socket.h> #include <netinet/in.h> int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
- sockfd → le fichier descripteur de la socket;
- level → niveau d'application de l'option (SOL_SOCKET, TCP, UDP, ...);
- optname → le nom de l'option (SO_REUSEADDR, SO_REUSEPORT, SO_KEEPALIVE, ...)
- optval, optlen → utilisé pour accéder aux options de la socket;
- le code retour varie entre 0 et -1 en cas d'erreur (errno est positionné)
Il existe plusieurs options de socket, les plus utilisées étant :
- SO_REUSEADDR → permet de réutiliser l'adresse de la socket tout de suite même si cette dernière est dans l'état wait;
- SO_REUSEPORT → permet de réutiliser le port de la socket tout de suite même si cette dernière est dans l'état wait;
- SO_KEEPALIVE → envoie des informations périodiquement pour tester si l'extrémité du tunnel est toujours présente;
Il faut maintenant attacher la socket à un port Internet et une adresse IP:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
- sockfd → le fichier descripteur de la socket;
- addr → une structure symbolisant l'adresse
struct sockaddr_in {
short sin_family; // e.g: AF_INET
unsigned short sin_port; // e.g: htons(3490)
struct in_addr sin_addr; // détaillé ci-dessous
char sin_zero[8]; // '0' habituellement
};
struct in_addr {
unsigned long s_addr; // initialiser avec inet_aton()
};
- addrlen → la taille de l'objet addr;
- le code retour varie entre 0 et -1 en cas d'erreur (errno est positionné)
On peut maintenant passer la socket en état d'écoute, elle est prête à recevoir des connexions:
int listen(int sockfd, int backlog)
- sockfd → le fichier descripteur de la socket;
- backlog → taille maximum de la file d'attente de la socket après laquelle le système répond avec ECONNREFUSED;
- le code retour varie entre 0 et -1 en cas d'erreur (errno est positionné)
On peut maintenant attendre une connexion:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- sockfd → le fichier descripteur de la socket;
- addr → l'adresse du client;
- addrlen → la taille de la structure addr;
- le code retour varie entre un entier positif qui correspond au descripteur de la socket cliente et -1 en cas d'erreur (errno est positionné)
Côté client
Après avoir créé la socket avec socket on peut se connecter à la partie serveur:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- sockfd → le fichier descripteur de la socket;
- addr → une structure symbolisant l'adresse (cf. ci-dessus)
- addrlen → la taille de l'objet addr;
- le code retour varie entre 0 et -1 en cas d'erreur (errno est positionné)
