Ressources informatiques

Ressources informatiques

Ressources informatiques

Créer un client UDP

Le client envoie une lettre au serveur qui renvoie la lettre suivante dans l'ordre alphabétique. Le serveur envoie le caractère '!' s'il reçoit un caractère qui n'est pas une lettre ou s'il reçoit la lettre 'z' ou la lettre 'Z'.

Se documenter

Code du client

/**
 * @brief  Envoie une lettre au serveur et reçoit la lettre suivante dans l'alphabet
 * @example  clientUdp 192.168.1.11 40000 a
 */
#include <string.h>     // pour memset()
#include <sys/socket.h> // pour socket(), setsockopt(), recvfrom(), sendto()
#include <sys/types.h>  // pour socket(), setsockopt(), recvfrom(), sendto()
#include <stdio.h>      // pour perror(), printf(), fprintf()
#include <arpa/inet.h>  // pour inet_pton(), htons()
#include <stdlib.h>     // pour strtol()

int main(int argc, char *argv[]) {
   int maSocket;
   struct sockaddr_in coupleIPPortServeur;
   long int adresseIPServeur;
   unsigned short numeroPortServeur;
   char lettre;
   char lettreReponse;
   socklen_t longueurServeur = sizeof(coupleIPPortServeur);

   // Tester le nombre d'arguments
   if (argc != 4) {
      fprintf(stderr, "usage : clientUdp <adresse_IP_serveur> <numero_de_port_serveur> <lettre>\nexemple : clientUdp 192.168.1.11 40000 a\n");
      return -1;
   }

   // Déterminer l'adresse IP et le numero de port du serveur
   // Adresse IP au format reseau
   if (inet_pton(AF_INET, argv[1], (void *)&adresseIPServeur) == -1)
   {perror("inet_pton"); return -1;}

   // Numéro de port
   numeroPortServeur = strtol(argv[2], NULL, 10);

   // Initialiser les structures a des octets de valeurs 0
   memset(&coupleIPPortServeur, 0, sizeof(struct sockaddr_in));

   // Créer la socket client en mode UDP
   if ((maSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
   {perror("socket"); return -1;}

   // Définir un temps maximal pour la réponse afin de ne pas bloquer
   // en cas de défaillance du serveur
   struct timeval timeout;
   timeout.tv_sec = 5;
   timeout.tv_usec = 0;
   if (setsockopt(maSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) == -1)
   {perror("setsockopt"); return -1;}

   // Initialiser l'adresse IP et le numéro de port du serveur
    // socket du domaine reseau
   coupleIPPortServeur.sin_family = AF_INET;
    // adresse IP
   coupleIPPortServeur.sin_addr.s_addr = adresseIPServeur;
    //affecter le numero de port de l'application
   coupleIPPortServeur.sin_port = htons(numeroPortServeur);

   lettre = argv[3][0];
    // Envoyer la requête
   if (sendto(maSocket, &lettre, sizeof(lettre), 0, (struct sockaddr *)(&coupleIPPortServeur), longueurServeur) == -1)
   {perror("sendto"); return -1;}

   // Recevoir la reponse
   if (recvfrom(maSocket, &lettreReponse, sizeof(lettreReponse), 0, (struct sockaddr *)(&coupleIPPortServeur), &longueurServeur) == -1)
   {perror("recvfrom"); return -1;}

   // Afficher la reponse
   printf("J'ai émis : %c, j'ai reçu : %c\n", lettre, lettreReponse);

   return 0;
}

Valider le protocole applicatif

J'utilise, pour valider le client, le serveur UDP correspondant.

doe@debian:~$ ./clientUdp 
usage : clientUdp <adresse_IP_serveur> <numero_de_port_serveur> <lettre>
exemple : clientUdp 192.168.1.11 40000 a
doe@debian:~$ ./clientUdp 192.168.1.101 30000 d
recvfrom: Resource temporarily unavailable
doe@debian:~$ ./clientUdp 192.168.1.101 40000 d
J'ai émis : d, j'ai reçu : e
doe@debian:~$ ./clientUdp 192.168.1.101 40000 D
J'ai émis : D, j'ai reçu : E
doe@debian:~$ ./clientUdp 192.168.1.101 40000 z
J'ai émis : z, j'ai reçu : !
doe@debian:~$ ./clientUdp 192.168.1.101 40000 Z
J'ai émis : Z, j'ai reçu : !
doe@debian:~$ ./clientUdp 192.168.1.101 40000 ?
J'ai émis : ?, j'ai reçu : !