123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- /* librairie standard ... */
- #include <stdlib.h>
- /* pour getopt */
- #include <unistd.h>
- /* déclaration des types de base */
- #include <sys/types.h>
- /* constantes relatives aux domaines, types et protocoles */
- #include <sys/socket.h>
- /* constantes et structures propres au domaine UNIX */
- #include <sys/un.h>
- /* constantes et structures propres au domaine INTERNET */
- #include <netinet/in.h>
- /* structures retournées par les fonctions de gestion de la base de
- données du réseau */
- #include <netdb.h>
- /* pour les entrées/sorties */
- #include <stdio.h>
- /* pour la gestion des erreurs */
- #include <errno.h>
- #define QUEUE_SIZE 5 // Taille de la file d'attente du listen()
-
- // Remplit le message de lg caractères motif
- 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);
-
- // Affiche l'usage de l'outil
- void print_usage(char* arg0);
-
- 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 serveur = 0; /* 0 not server, 1 server */
- int emetteur = 0; /* 0 not sender, 1 sender */
- int recepteur = 0; /* 0 not receiver, 1 receiver */
-
- while ((c = getopt(argc, argv, "pn:sul:CSer")) != -1) {
- switch (c) {
- case 'p':
- if (source == 1) {
- print_usage(argv[0]);
- exit(1);
- }
- source = 0;
- break;
-
- case 's':
- if (source == 0) {
- print_usage(argv[0]);
- 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 || nb_message <= 0) {
- print_usage(argv[0]);
- 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) {
- print_usage(argv[0]);
- exit(1);
- }
- break;
- /* -c and -e options stand only for TCP exchange */
- case 'C':
- client=1;
- if (udp || serveur) {
- print_usage(argv[0]);
- exit(0);
- }
- break;
- case 'S':
- serveur = 1;
- if (udp || client) {
- print_usage(argv[0]);
- exit(0);
- }
- break;
- case 'e':
- emetteur=1;
- if (udp || recepteur) {
- print_usage(argv[0]);
- exit(0);
- }
- break;
- case 'r':
- recepteur=1;
- if (udp || emetteur) {
- print_usage(argv[0]);
- exit(0);
- }
- break;
- default:
- print_usage(argv[0]);
- break;
- }
- }
-
- // Little verification of TCP arguments.
- // Machine must be a server or a client as once,
- // as well as a sender or receiver.
- if (!udp) {
- if ((!recepteur && !emetteur) || (!serveur && !client)) {
- print_usage(argv[0]);
- exit(0);
- }
- }
-
- // Variable qui va stocker le nom logique de la machine avec qui on communique
- char* nom_machine_distante;
-
- //Allocation de la variable stockant un message, il est de la taille donnée en paramètre
- char* message = malloc(lg * sizeof(char));
-
- // Recuperation du port
- int port=atoi(argv[argc-1]);
-
- // Default set of packet length : 30 bytes
- if (lg == -1) {
- lg=30;
- }
-
- // If number of messages is not fixed for the source, it is set to 10 messages
- if (nb_message == -1 && (source || !udp)) {
- nb_message = 10 ;
- }
-
-
- //Affichage des informations de communication initiée
- if (source || emetteur) {
- //Recuperation du nom logique
- nom_machine_distante=argv[argc-2];
- printf("SOURCE:lg_mesg_emis=%d,port=%d,nb_envois=%d,TP=%s",
- lg,port,nb_message,(udp)?"UDP":"TCP");
- if (client) {
- printf(",dest=%s",nom_machine_distante);
- }
- printf("\n");
- } 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 (client) {
-
- // 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 ou reception des messages
- for (int i = 0; i < nb_message; i++) {
-
- if (emetteur){
- // 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);
- }
- if (recepteur) {
- if ((read(sock, message, longueur_message)) < 0){
- printf("échec du read\n") ; exit(1) ;}
- afficher_message_reception(message, longueur_message,i+1) ;
-
- }
- }
-
- // Close socket to avoid dangling connections
- close(sock);
- }
-
- // The server shall accept the connexion
- if (serveur) {
- // 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) ;
- }
-
- // On crée un processus pour chaque connexion TCP acceptée
- 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 ++) {
- // Server sends packets with -e
- if (emetteur){
- // Construction du message
- construire_message(message, 'a' + (i % 26), lg, i+1);
- afficher_message_envoi(message,lg,i+1);
- // Envoi du message
- write(sock_bis,message,longueur_message);
- }
- // Server receives packets with -r
- if (recepteur) {
- 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<lg;i++) message[i] = motif;
- }
-
- void afficher_message_envoi(char *message, int lg, int numero_envoi) {
- int i;
- printf("SOURCE: Envoi n°%d (%d) [",numero_envoi,lg);
-
- for (i=0;i<lg;i++){
- printf("%c", message[i]);
- }
- printf("]\n");
- }
-
- void afficher_message_reception(char *message, int lg, int numero_envoi) {
- int i;
- printf("PUITS: Reception n°%d (%d) [",numero_envoi,lg);
-
- for (i=0;i<lg;i++){
- printf("%c", message[i]);
- }
- printf("]\n");
-
- }
-
- void print_usage(char* arg0) {
- printf("usage: %s [-psuCSer] [-n nb_messages] [-l mess_length] [host] <port>\n", arg0);
- printf("parameters: host With -s or -C, address of the host to connect to. Required with -s or -C.\n");
- printf(" port Port to connect or bind to. Required.\n");
- printf("options: -l mess_length Size of the messages to send. Min 5. Max 1400. Default 30.\n");
- printf(" -n nb_messages Number of messages to send. Min 1. Default 10. Ignored with -p.\n");
- printf(" -p Runs a TCP/UDP sink. Incompatible with -s.\n");
- printf(" -s Runs a TCP/UDP faucet. Incompatible with -p.\n");
- printf(" -C Client of a TCP connexion. Incompatible with -S and -u. Requires -e or -r.\n");
- printf(" -S Server of a TCP connexion. Incompatible with -C and -u. Requires -e or -r.\n");
- printf(" -e Packets issuer of a TCP connexion. Incompatible with -r and -u.\n");
- printf(" -r Packets receiver of a TCP connexion. Incompatible with -e and -u.\n");
-
- }
|