Unix Socket - Fonctions de base

Ce chapitre décrit les principales fonctions de socket requises pour écrire un client et un serveur TCP complets.

Le diagramme suivant montre l'interaction complète du client et du serveur -

La fonction socket

Pour effectuer des E / S réseau, la première chose qu'un processus doit faire est d'appeler la fonction socket, en spécifiant le type de protocole de communication souhaité et la famille de protocoles, etc.

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

int socket (int family, int type, int protocol);

Cet appel renvoie un descripteur de socket que vous pouvez utiliser dans les appels système ultérieurs ou -1 en cas d'erreur.

Paramètres

family - Il spécifie la famille de protocoles et est l'une des constantes ci-dessous -

Famille La description
AF_INET Protocoles IPv4
AF_INET6 Protocoles IPv6
AF_LOCAL Protocoles de domaine Unix
AF_ROUTE Routage des sockets
AF_KEY Prise Ket

Ce chapitre ne couvre pas les autres protocoles sauf IPv4.

type- Il spécifie le type de socket que vous souhaitez. Il peut prendre l'une des valeurs suivantes -

Type La description
SOCK_STREAM Prise de flux
SOCK_DGRAM Prise datagramme
SOCK_SEQPACKET Socket de paquet séquencé
SOCK_RAW Prise brute

protocol - L'argument doit être défini sur le type de protocole spécifique donné ci-dessous, ou sur 0 pour sélectionner la valeur par défaut du système pour la combinaison donnée de famille et de type -

Protocole La description
IPPROTO_TCP Protocole de transport TCP
IPPROTO_UDP Protocole de transport UDP
IPPROTO_SCTP Protocole de transport SCTP

La fonction de connexion

La fonction de connexion est utilisée par un client TCP pour établir une connexion avec un serveur TCP.

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

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

Cet appel renvoie 0 s'il se connecte avec succès au serveur, sinon il renvoie -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • serv_addr - C'est un pointeur vers la structure sockaddr qui contient l'adresse IP et le port de destination.

  • addrlen - Réglez-le sur sizeof (struct sockaddr).

La fonction bind

La fonction de liaison attribue une adresse de protocole local à un socket. Avec les protocoles Internet, l'adresse de protocole est la combinaison d'une adresse IPv4 32 bits ou d'une adresse IPv6 128 bits, avec un numéro de port TCP ou UDP 16 bits. Cette fonction est appelée uniquement par le serveur TCP.

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

int bind(int sockfd, struct sockaddr *my_addr,int addrlen);

Cet appel renvoie 0 s'il se lie avec succès à l'adresse, sinon il renvoie -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • my_addr - C'est un pointeur vers struct sockaddr qui contient l'adresse IP locale et le port.

  • addrlen - Réglez-le sur sizeof (struct sockaddr).

Vous pouvez mettre votre adresse IP et votre port automatiquement

Une valeur 0 pour le numéro de port signifie que le système choisira un port aléatoire, et la valeur INADDR_ANY pour l'adresse IP signifie que l'adresse IP du serveur sera attribuée automatiquement.

server.sin_port = 0;  		     
server.sin_addr.s_addr = INADDR_ANY;

NOTE- Tous les ports inférieurs à 1024 sont réservés. Vous pouvez définir un port au-dessus de 1024 et en dessous de 65535 à moins qu'ils ne soient ceux utilisés par d'autres programmes.

La fonction d' écoute

La fonction d' écoute est appelée uniquement par un serveur TCP et elle effectue deux actions -

  • La fonction Listen convertit une socket non connectée en une socket passive, indiquant que le noyau doit accepter les demandes de connexion entrantes dirigées vers cette socket.

  • Le deuxième argument de cette fonction spécifie le nombre maximum de connexions que le noyau doit mettre en file d'attente pour cette socket.

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

int listen(int sockfd,int backlog);

Cet appel renvoie 0 en cas de succès, sinon il renvoie -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • backlog - C'est le nombre de connexions autorisées.

La fonction d' acceptation

La fonction d' acceptation est appelée par un serveur TCP pour renvoyer la prochaine connexion terminée depuis l'avant de la file d'attente de connexion terminée. La signature de l'appel est la suivante -

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

int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

Cet appel renvoie un descripteur non négatif en cas de succès, sinon il renvoie -1 en cas d'erreur. Le descripteur renvoyé est supposé être un descripteur de socket client et toutes les opérations de lecture-écriture seront effectuées sur ce descripteur pour communiquer avec le client.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • cliaddr - Il s'agit d'un pointeur vers la structure sockaddr qui contient l'adresse IP et le port du client.

  • addrlen - Réglez-le sur sizeof (struct sockaddr).

La fonction d' envoi

La fonction d' envoi est utilisée pour envoyer des données sur des sockets de flux ou des sockets de datagramme CONNECTÉS. Si vous souhaitez envoyer des données via des sockets de datagramme NON CONNECTÉS, vous devez utiliser la fonction sendto ().

Vous pouvez utiliser l' appel système write () pour envoyer des données. Sa signature est la suivante -

int send(int sockfd, const void *msg, int len, int flags);

Cet appel renvoie le nombre d'octets envoyés, sinon il retournera -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • msg - C'est un pointeur vers les données que vous souhaitez envoyer.

  • len - C'est la longueur des données que vous souhaitez envoyer (en octets).

  • flags - Il est mis à 0.

La fonction recv

La fonction recv est utilisée pour recevoir des données sur des sockets de flux ou des sockets de datagramme CONNECTÉS. Si vous souhaitez recevoir des données sur des sockets de datagramme NON CONNECTÉS, vous devez utiliser recvfrom ().

Vous pouvez utiliser l' appel système read () pour lire les données. Cet appel est expliqué dans le chapitre sur les fonctions d'assistance.

int recv(int sockfd, void *buf, int len, unsigned int flags);

Cet appel renvoie le nombre d'octets lus dans le tampon, sinon il renverra -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • buf - C'est le tampon dans lequel lire les informations.

  • len - C'est la longueur maximale du tampon.

  • flags - Il est mis à 0.

La fonction sendto

La fonction sendto est utilisée pour envoyer des données sur des sockets de datagramme NON CONNECTÉS. Sa signature est la suivante -

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

Cet appel renvoie le nombre d'octets envoyés, sinon il renvoie -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • msg - C'est un pointeur vers les données que vous souhaitez envoyer.

  • len - C'est la longueur des données que vous souhaitez envoyer (en octets).

  • flags - Il est mis à 0.

  • to - C'est un pointeur vers la structure sockaddr pour l'hôte où les données doivent être envoyées.

  • tolen - Il est défini sur sizeof (struct sockaddr).

La fonction recvfrom

La fonction recvfrom est utilisée pour recevoir des données à partir de sockets de datagramme NON CONNECTÉS .

int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);

Cet appel renvoie le nombre d'octets lus dans le tampon, sinon il renvoie -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • buf - C'est le tampon dans lequel lire les informations.

  • len - C'est la longueur maximale du tampon.

  • flags - Il est mis à 0.

  • from - C'est un pointeur vers struct sockaddr pour l'hôte où les données doivent être lues.

  • fromlen - Il est défini sur sizeof (struct sockaddr).

La fonction close

La fonction de fermeture est utilisée pour fermer la communication entre le client et le serveur. Sa syntaxe est la suivante -

int close( int sockfd );

Cet appel renvoie 0 en cas de succès, sinon il renvoie -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

La fonction d' arrêt

La fonction d' arrêt est utilisée pour fermer en douceur la communication entre le client et le serveur. Cette fonction donne plus de contrôle par rapport à la fonction de fermeture . Ci-dessous est la syntaxe de l' arrêt -

int shutdown(int sockfd, int how);

Cet appel renvoie 0 en cas de succès, sinon il renvoie -1 en cas d'erreur.

Paramètres

  • sockfd - C'est un descripteur de socket renvoyé par la fonction socket.

  • how - Mettez l'un des nombres -

    • 0 - indique que la réception n'est pas autorisée,

    • 1 - indique que l'envoi n'est pas autorisé, et

    • 2- indique que l'envoi et la réception ne sont pas autorisés. Quand how est défini sur 2, c'est la même chose que close ().

La fonction de sélection

La fonction de sélection indique lequel des descripteurs de fichier spécifiés est prêt pour la lecture, prêt pour l'écriture ou a une condition d'erreur en attente.

Lorsqu'une application appelle recv ou recvfrom , elle est bloquée jusqu'à ce que les données arrivent pour ce socket. Une application peut effectuer d'autres traitements utiles alors que le flux de données entrant est vide. Une autre situation se produit lorsqu'une application reçoit des données de plusieurs sockets.

L'appel de recv ou recvfrom sur un socket qui n'a pas de données dans sa file d'attente d'entrée empêche la réception immédiate des données d'autres sockets. L'appel de fonction de sélection résout ce problème en permettant au programme d'interroger tous les descripteurs de socket pour voir s'ils sont disponibles pour des opérations de lecture et d'écriture non bloquantes.

Voici la syntaxe de select -

int select(int  nfds, fd_set  *readfds, fd_set  *writefds, fd_set *errorfds, struct timeval *timeout);

Cet appel renvoie 0 en cas de succès, sinon il renvoie -1 en cas d'erreur.

Paramètres

  • nfds- Il spécifie la plage de descripteurs de fichiers à tester. La fonction select () teste les descripteurs de fichier dans la plage de 0 à nfds-1

  • readfds- Il pointe vers un objet de type fd_set qui en entrée, spécifie les descripteurs de fichier à vérifier pour être prêts à lire, et en sortie, indique quels descripteurs de fichier sont prêts à lire. Il peut être NULL pour indiquer un ensemble vide.

  • writefds- Il pointe vers un objet de type fd_set qui en entrée, spécifie les descripteurs de fichier à vérifier pour être prêts à écrire, et en sortie, indique quels descripteurs de fichier sont prêts à écrire. Il peut être NULL pour indiquer un ensemble vide.

  • exceptfds- Il pointe vers un objet de type fd_set qui, en entrée, spécifie les descripteurs de fichier à vérifier pour les conditions d'erreur en attente, et en sortie indique, quels descripteurs de fichier ont des conditions d'erreur en attente. Il peut être NULL pour indiquer un ensemble vide.

  • timeout- Il pointe vers une structure timeval qui spécifie la durée pendant laquelle l'appel de sélection doit interroger les descripteurs pour une opération d'E / S disponible. Si la valeur du délai d'expiration est 0, select retournera immédiatement. Si l'argument timeout est NULL, select bloquera jusqu'à ce qu'au moins un descripteur de fichier / socket soit prêt pour une opération d'E / S disponible. Sinon, select retournera une fois que le délai d'expiration s'est écoulé OU lorsqu'au moins un descripteur de fichier / socket est prêt pour une opération d'E / S.

La valeur de retour de select est le nombre de descripteurs spécifiés dans les ensembles de descripteurs de fichiers prêts pour les E / S. Si la limite de temps spécifiée par le champ timeout est atteinte, sélectionnez return 0. Les macros suivantes existent pour manipuler un ensemble de descripteurs de fichiers -

  • FD_CLR(fd, &fdset)- Efface le bit du descripteur de fichier fd dans le jeu de descripteurs de fichier fdset.

  • FD_ISSET(fd, &fdset)- Renvoie une valeur différente de zéro si le bit du descripteur de fichier fd est défini dans l'ensemble de descripteurs de fichier pointé par fdset , et 0 dans le cas contraire.

  • FD_SET(fd, &fdset) - Définit le bit du descripteur de fichier fd dans le jeu de descripteurs de fichier fdset.

  • FD_ZERO(&fdset) - Initialise l'ensemble de descripteurs de fichier fdset pour qu'il ait zéro bit pour tous les descripteurs de fichier.

Le comportement de ces macros n'est pas défini si l'argument fd est inférieur à 0 ou supérieur ou égal à FD_SETSIZE.

Exemple

fd_set fds;

struct timeval tv;

/* do socket initialization etc.
tv.tv_sec = 1;
tv.tv_usec = 500000;

/* tv now represents 1.5 seconds */
FD_ZERO(&fds);

/* adds sock to the file descriptor set */
FD_SET(sock, &fds); 

/* wait 1.5 seconds for any data to be read from any single socket */
select(sock+1, &fds, NULL, NULL, &tv);

if (FD_ISSET(sock, &fds)) {
   recvfrom(s, buffer, buffer_len, 0, &sa, &sa_len);
   /* do something */
}
else {
   /* do something else */
}