Traitement des informations

(en mode connecté)

 

Les includes

Si ce n'est déjà fait, certains includes seront nécessaires:

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

 

Lire ou écrire des données

Comme vous le savez déjà, sous Unix, tout est fichier. Par conséquent, il sera tout à fait possible d'utiliser les fonctions read ou write pour lire ou envoyer des données. Il suffira d'utiliser le descripteur de socket comme descripteur de fichier...Je n'en dirais pas plus.

Mais il existe des fonctions plus appropriées:

Tout d'abord envoyer une chaîne à destination d'une autre socket:

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

 

Image non trouvée !Send ne peut être utilisé qu'avec les sockets connectées !

En entrée:

s est l'identifiant du socket

msg est un buffer contenant le message à envoyer

len est la longueur du texte à envoyer

flags contenant une ou plusieurs options:

Valeur Désignation
MSG_OOB Permet d'émettre des données hors-bande sur un socket qui l'autorise (ex. SOCK_STREAM)
MSG_DONTROUTE Ne pas passer par une passerelle mais uniquement vers les hôtes directement connecté au réseau
MSG_DONTWAIT Active le mode non-bloquant (retournera EAGAIN pour indiquer que cela aurait du être bloquant)
MSG_NOSIGNAL Ne pas envoyer le signal SIGPIPE lorsque le correspondant coupe la connexion. EPIPE sera renvoyé à la place.

 

En sortie:

La fonction retoutne -1 si erreur et errno contient le code erreur, sinon, il s'agit de la taille du texte transmis.

Voici quelques exemples de codes erreurs:

Valeur Désignation
EBADF Descripteur de socket invalide.
ENOTSOCK L'argument s n'est pas une socket.
EFAULT Un paramètre pointe en dehors de l'espace d'adresssage accessible.
EMSGSIZE La socket nécessite une emission intégrale du message mais la taille de celui-ci ne le permet pas.
EAGAIN ou EWOULDBLOCK La socket est non-bloquante et l'opération demandée bloquerait.
ENOBUFS La file d'émission de l'interface réseau est pleine.Cause: panne ou saturation passagère
EINTR Un signal a été reçu
ENOMEM Pas assez de mémoire pour le noyau.
EINVAL Un argument invalide a été transmis.
EPIPE L'écriture est impossible.Le processus recevra également un signal SIGPIPE sauf s'il a activée l'option MSG_NOSIGNAL.

 

Puis recevoir une chaîne provenant d'une autre socket:

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

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

Image non trouvée !recvfrom pourra servir à la lecture de données que la socket soit orientée connexion ou non. Dans notre cas, càd en mode connecté, from devra être nul.

En entrée:

s est le descripteur de socket

buf est une zone mémoire qui recevra le texte

len est la taille du buffer.

flags est un drapeau permettant de gérer les options suivantes:

Valeur Désignation
MSG_OOB Permet d'émettre des données hors-bande sur un socket qui l'autorise (ex. SOCK_STREAM)
MSG_PEEK Lire les données en attente dans le file sans les retirer. Une lecture ultérieur pourra alors récupérer ces données.
MSG_WAITALL Attendre (lecture bloquante) jusqu'à la complétude de la requète. (sauf signaux, ou erreur/déconnexion)
MSG_ERRQUEUE Lire les erreurs provenant de la file d'erreur de la socket.

 

Ces trois routines renvoient la longueur du message si elles réussissent. Si un message est trop long pour tenir dans le buffer, les octets supplémentaires peuvent être abandonnés suivant le type de socket utilisé.

Si aucun message n'est disponible sur la socket, les fonctions de réception se mettent en attente, à moins que la socket soit non bloquante (voir ci-après ) auquel cas la valeur -1 est renvoyée, et errno est positionnée à EAGAIN.

Les fonctions de réception renvoient normalement les données disponibles dans la limite du paramètre len sans attendre d'avoir reçu le nombre exact réclamé.

 

Image non trouvée !Les fonctions send () et recv () sont bloquantes (ou plus exactement: le socket). On pourra les rendre non bloquantes en utilisant:

Sous Windows:

u_long arg = 1;
ioctlsocket (socket, FIONBIO, &arg);
Pour le rendre de nouveau bloquant, passé la valeur 0 dans arg.

Sous Linux:

fcntl(socket, F_SETFL, O_NONBLOCK);

avec socket le descripteur du socket !

 

AttentionSuite à un send de données d'une taille précise, il n'est pas obligatoire que recv retourne en une seule opération l'ensemble de ces données. Il sera donc peut être nécessaire de faire un second, un troisième ,... recv pour obtenir le reste des données. Il faudra peut être mettre en place un système indiquant lors du send la taille totale des données effectivement envoyées, ce qui permettra lors de recv de savoir si le paquet de données est complet ou si il est nécessaire de relancer un recv.