/* librairie standard ... */ #include /* pour getopt */ #include /* déclaration des types de base */ #include /* constantes relatives aux domaines, types et protocoles */ #include /* constantes et structures propres au domaine UNIX */ #include /* constantes et structures propres au domaine INTERNET */ #include /* structures retournées par les fonctions de gestion de la base de données du réseau */ #include /* pour les entrées/sorties */ #include /* pour la gestion des erreurs */ #include #define QUEUE_SIZE 5 void construire_message(char* message, char motif, int lg, int numero_envoi); // Affichage distinct entre envoi et reception pour une facilité d'utilisation void afficher_message_envoi(char *message, int lg, int numero_envoi); void afficher_message_reception(char *message, int lg, int numero_envoi); int main (int argc, char **argv) { int c; extern char *optarg; extern int optind; int nb_message = -1; /* Nb de messages à envoyer ou à recevoir, par défaut : 10 en émission, infini en réception */ int source = -1 ; /* 0=puits, 1=source */ int udp = 0; /* 0=TCP, 1=UDP */ int lg = -1; /* Longueur des messages à envoyer ou recevoir: par défaut 30 octets */ int client = 0 /* 0 not client, 1 client */ int emetteur = 0 /* 0 not sender, 1 sender */ while ((c = getopt(argc, argv, "pn:sul:ce")) != -1) { switch (c) { case 'p': if (source == 1) { printf("usage: cmd [-p|-s][-n ##]\n"); exit(1); } source = 0; break; case 's': if (source == 0) { printf("usage: cmd [-p|-s][-n ##]\n"); exit(1) ; } source = 1; break; case 'n': nb_message = atoi(optarg); // Packets are numerotated with 5 figures, which means the number of // packets send can't be bigger than (or equal) 10 ** 6 if(nb_message >= 100000) { printf("Too many packets"); exit(1); } break; case 'u': udp=1; break; case 'l': lg=atoi(optarg); // A TCP packet is roughly 1500 bytes. We allow for some overhead. // We provide an MTU of 1400 bytes. // We also to send at least a message of 5 characters length for indice packet if(lg >= 1400 || lg < 5) { printf("Messages too long"); exit(1); } break; /* -c and -e options stand only for TCP exchange */ case 'c': client=1; if (udp == 1){ printf("No option -c for UDP"); exit(0); } break; case 'e': emetteur=1; if (udp == 1){ printf("No option -e for UDP"); exit(0); } break; default: printf("usage: cmd [-p|-s][-n ##]\n"); break; } } char* nom_machine_distante; // Recuperation du port int port=atoi(argv[argc-1]); //port = htons(port); // Default set of packet length : 30 bytes if (lg == -1) { lg=30; } //Allocation du message, il est de la taille donnée en paramètre char* message = malloc(lg * sizeof(char)); if (source == -1) { printf("usage: cmd [-p|-s][-n ##]\n"); exit(1) ; } // If number of messages is not fixed for the source, it is set to 10 messages if (nb_message == -1 && source ) { nb_message = 10 ; } //Affichage des informations de communication initiée if (source == 1) { //Recuperation du nom logique nom_machine_distante=argv[argc-2]; printf("SOURCE:lg_mesg_emis=%d,port=%d,nb_envois=%d,TP=%s,dest=%s\n", lg,port,nb_message,(udp)?"UDP":"TCP",nom_machine_distante); } else { printf("PUITS:lg_mesg-lu=%d,port=%d,nb_receptions=",lg,port); if (nb_message!=-1 && !source) { printf("infini"); } else { printf("%d",nb_message); } printf(", TP=%s\n",(udp)?"UDP":"TCP"); } /*******************************UDP COMMUNICATION*************************************/ if (udp==1){ // Creation du socket local int sock= socket(AF_INET,SOCK_DGRAM,0); if (source==1) { // Creation de l'adresse du socket distant struct hostent *hp ; struct sockaddr_in adr_dest; int longueur_adr_dest = sizeof(adr_dest); int longueur_message = lg; memset((char *)& adr_dest, 0, sizeof(adr_dest)) ; adr_dest.sin_family=AF_INET; adr_dest.sin_port=port; if ((hp = gethostbyname(nom_machine_distante)) == NULL) { printf("erreur gethostbyname\n") ; exit(1) ; } memcpy( (char*)&(adr_dest.sin_addr.s_addr), hp->h_addr, hp->h_length ) ; for (int i = 0; i < nb_message; i++) { // Construction du message construire_message(message, 'a' + (i % 26), lg, i+1); // Envoi du message afficher_message_envoi(message,lg,i+1); sendto(sock,message,longueur_message,0,(struct sockaddr*)&adr_dest,longueur_adr_dest); } } else { // Creation de l'adresse du socket distant struct sockaddr_in adr_locale; int longueur_adr_locale = sizeof(adr_locale); memset((char *)& adr_locale, 0, sizeof(adr_locale)) ; adr_locale.sin_family=AF_INET; adr_locale.sin_port=port; adr_locale.sin_addr.s_addr = INADDR_ANY; // Bind the local socket to any local address (ie any available interface) if (bind(sock, (struct sockaddr *) &adr_locale, longueur_adr_locale) == -1) { printf("failed to bind\n"); exit(1); } // Suivi du numéro de message reçu int k=0; while (recvfrom(sock, message, lg, 0, NULL, NULL)) { k++; // Afficher notre seule et unique triste message afficher_message_reception(message, lg, k); } } } /*******************************TCP COMMUNICATION*************************************/ else{ // Creation du socket local int sock= socket(AF_INET,SOCK_STREAM,0); //The server shall establish the connexion if (source==1) { // Creation de l'adresse du socket distant struct hostent *hp ; struct sockaddr_in adr_dest; int longueur_adr_dest = sizeof(adr_dest); int longueur_message = lg; memset((char *)& adr_dest, 0, sizeof(adr_dest)) ; adr_dest.sin_family=AF_INET; adr_dest.sin_port=port; if ((hp = gethostbyname(nom_machine_distante)) == NULL) { printf("erreur gethostbyname\n") ; exit(1) ; } memcpy( (char*)&(adr_dest.sin_addr.s_addr), hp->h_addr, hp->h_length ) ; // Demande de connexion int succ; if ((succ=connect(sock,(struct sockaddr*) &adr_dest,longueur_adr_dest))!=0){ printf("Echec connect"); exit(1); } // Envoi des messages for (int i = 0; i < nb_message; i++) { // Construction du message construire_message(message, 'a' + (i % 26), lg, i+1); afficher_message_envoi(message,lg,i+1); // Envoi du message write(sock,message,longueur_message); } // Close socket to avoid dangling connections close(sock); } else { // Creation de l'adresse du socket local struct sockaddr_in adr_locale; socklen_t longueur_adr_locale = sizeof(adr_locale); int longueur_message = lg; memset((char *)& adr_locale, 0, sizeof(adr_locale)) ; adr_locale.sin_family=AF_INET; adr_locale.sin_port=port; adr_locale.sin_addr.s_addr = INADDR_ANY; // Bind the local socket to any local address (ie any available interface) if (bind(sock, (struct sockaddr *) &adr_locale, longueur_adr_locale) == -1) { printf("failed to bind\n"); exit(1); } // set listening queue size if (listen(sock, QUEUE_SIZE) == -1) { printf("échec et mat listen\n"); exit(1); } int sock_bis; while(1) { // Accept a single connection on the main thread if ((sock_bis = accept( sock, (struct sockaddr *)&adr_locale, &longueur_adr_locale)) == -1){ printf("échec du accept\n") ; exit(1) ; } printf("socket accepte:%d\n",sock_bis); switch (fork() ) { case - 1 : /* il y a une erreur */ printf("erreur fork\n") ; exit(1) ; case 0 : /* on est dans le proc. fils */ close(sock) ; /* fermeture socket du proc. père */ for (int i=0 ; i < nb_message ; i ++) { if ((read(sock_bis, message, longueur_message)) < 0){ printf("échec du read\n") ; exit(1) ;} afficher_message_reception(message, longueur_message,i+1) ; } close(sock_bis); exit(0) ; default : /* on est dans le proc. père */ close(sock_bis) ; /* fermeture socket du proc. fils Connexion stay opened for further exchanges */ } } } } exit(0); } void construire_message(char *message, char motif, int lg, int numero_envoi) { int i; snprintf(message, lg,"% 5d",numero_envoi); for (i=5;i