Programmation Avancée en C


socket_UDP_client.c

00001 #include <stdio.h> 
00002 #include <stdlib.h> 
00003 #include <unistd.h>
00004 #include <netinet/in.h>
00005 #include <sys/socket.h>
00006 #include <arpa/inet.h>
00007 #define _POSIX_C_SOURCE 2 /* Nécessaire sur certains Linux. */
00008 #include <netdb.h>
00009 #include <string.h>
00010 
00011 #define MAX_SIZE 256
00012 
00013 void error(char * msg);      // cf. ligne /*@\ref{network::socket_TCP_client::error} du listing~\ref{network::socket_TCP_client}@*/
00014 void doit(int sockfd, struct sockaddr_in * serv) {
00015     char requete[MAX_SIZE] = "Luc, je suis ton père!";
00016     char reponse[MAX_SIZE];
00017     size_t request_size = strlen(requete) + 1;
00018 
00019     ssize_t n = sendto(sockfd, requete, request_size, 0,
00020                        (struct sockaddr *) serv, sizeof(*serv)); /*@\label{network::socket_UDP_client::sendto}@*/
00021     if ( n != request_size) error("[sendto]");
00022     printf("Requête envoyée à %s:%d : <%s> (%ld octets)\n",
00023            inet_ntoa(serv->sin_addr), ntohs(serv->sin_port), requete, (long) n);
00024 
00025     n = recvfrom(sockfd, reponse, MAX_SIZE-1, 0, NULL, NULL); /*@\label{network::socket_UDP_client::recvfrom}@*/
00026     if (n < 0) error("[recvfrom]");
00027     reponse[MAX_SIZE-1] = '\0'; // précaution pour affichage
00028     printf("Réponse obtenue: <%s> (%ld octets)\n", reponse, (long) n);
00029 }
00030 
00031 int main(int argc, char* argv[]) // Client UDP 
00032 {
00033     char * servname = "localhost";
00034     char * port     = "6666";
00035     struct addrinfo hints, *res;
00036     int err, sockfd = -1;
00037 
00038     switch (argc) { // Traitement des arguments de la ligne de commande 
00039     case 3:  port     = argv[2];
00040     case 2:  servname = argv[1]; break;
00041     case 1:  break;
00042     default: fprintf(stderr, "Usage: %s [servname [port]]\n",argv[0]);
00043              return EXIT_FAILURE;
00044     }
00045     /*** Construction de l'adresse de socket du serveur ***/
00046     memset(&hints, 0, sizeof(hints));
00047     hints.ai_flags    = AI_CANONNAME; // On veut une résolution de nom.
00048     hints.ai_family   = AF_INET;      // Adresse IPv4 uniquement.
00049     hints.ai_socktype = SOCK_DGRAM;   // Socket non connectée.
00050     if ((err = getaddrinfo(servname, port, &hints, &res)) < 0)  {
00051         if (err == EAI_SYSTEM) error("[getaddrinfo]");
00052         fprintf(stderr, "[getaddrinfo] on %s : %s\n", servname, gai_strerror(err));
00053         return EXIT_FAILURE;
00054     }
00055     for(; res != NULL; res = res->ai_next) {
00056         /*** Création d'une socket ***/ 
00057         sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
00058         if (sockfd < 0) continue;
00059         break; // si on arrive ici, on a réussi à créer la socket
00060     }
00061     if (sockfd  < 0)   error("[socket]"); 
00062     doit(sockfd, (struct sockaddr_in *) res->ai_addr); // gestion des requêtes
00063 
00064     close(sockfd);     // Fermeture de la socke
00065     freeaddrinfo(res); // Ne pas oublier de libérer l'espace alloué à res!
00066     return EXIT_SUCCESS;
00067 }
00068 
00069 void error(char * msg) {
00070     perror(msg);
00071     exit(EXIT_FAILURE);
00072 }