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 : !