/*********************************************************** B. Dupouy / modifie par E. Lecolinet pour comm avec Java *********************************************************/ #include #include #include #include #include #include #include #include /* Ce fichier montre un exemple de "pseudo-serveur" pour communiquer * avec une interface graphique ecrite en Java (ou autre). * L'interface joue le role du "client" et envoie des requetes quand * l'utilisateur clique sur quelque chose. Le "serveur" receptionne * ces requetes, effectue un calcul a partir des donnees contenues * dans la requete et renvoie un resultat au client. Le client * (c'est-a-dire l'interface) recupere ce resultat et l'affiche * de maniere ad hoc * * Remarque: contrairement a un serveur classique il n'y pas de fork * ou equivalent: le serveur travaille en sequence avec son unique client * de telle sorte que les resultats soient affiches dans le bon ordre * pas l'interface. D'autres architectures pourraient egalement etre * employees a condition de gerer les eventuelles incoherences qui * pourraient alors survenir (si les actions de l'utilisateur sur * l'interface n'engendrent pas des "calculs" exactement dans le * meme ordre */ /**************** Effectue le "calcul" demande par le client ********/ void Calcule(char *entree, char *sortie, int sortie_len) { static int no_calcul = 0; /* ne pas oublier le \n a la fin ! */ /* att: sortie est supposee etre "assez longue" ! */ sprintf(sortie, "Calcul No= %d - Entree= [%s]\n", no_calcul++, entree); } /**************** Fonction de gestion des communications ************/ static void GereComm(int sock_com) { char entree[1024], sortie[1024]; int readstat; int pos; static char entete[] = "Debut de comm.\n"; if (write(sock_com, entete, strlen(entete)) < 0) perror("! Erreur ecriture message"); pos = 0; do { if ((readstat = read(sock_com, entree + pos, sizeof entree - pos)) < 0) { perror("! Erreur lecture Message") ; return; } if (readstat == 0) { fprintf(stderr, "> Fin de connexion\n"); return; } pos += readstat; } while (entree[pos - 1] !='\n') ; entree[pos - 2] = 0; fprintf(stderr, ">Recu: lstr=[%s]\n", entree); Calcule(entree, sortie, sizeof(sortie)-1); fprintf(stderr, ">send: lstr=[%s]\n", sortie); if (write(sock_com, sortie, strlen(sortie)) < 0) { perror("! Erreur ecriture message") ; exit(2); } } /**************** Serveur *********************************************/ static char MESSAGE[] = "Reponse de pid \n"; int main(int argc, char *argv[]) { struct sockaddr_in le_serveur ; // int taille; socklen_t taille; int sock_serv; if (argc != 2) { printf("Usage: %s port\n", argv[0]); exit(1); } if ((sock_serv = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("Serveur: erreur ouverture socket en mode connecte\n") ; exit(1); } /* construction de l'adresse du serveur */ le_serveur.sin_family = AF_INET; le_serveur.sin_addr.s_addr = INADDR_ANY; le_serveur.sin_port = htons(atoi(argv[1])); sprintf(MESSAGE+15, " %d fils de %d",(int)getpid(), (int)getppid()); printf("Ici le serveur %s\n", MESSAGE); taille = sizeof(le_serveur) ; if (bind(sock_serv, (struct sockaddr *)&le_serveur, taille) < 0) { perror("Serveur : erreur sur bind "); exit(1); } /* Verifications sur le serveur : */ if (getsockname(sock_serv, (struct sockaddr *)&le_serveur, &taille) < 0) { perror("Serveur : erreur sur getsocketname "); exit(1); } printf(" Numero de mon port : %d\n", ntohs(le_serveur.sin_port)) ; printf(" **********************************\n"); /* Le serveur se met en attente sur le socket d ecoute */ listen(sock_serv, 5); /* Boucle d'attente des messages du client. * Envoie un "resultat" en retour. * Remarque: pas de fork: ce serveur communique sequentiellement * avec son unique client */ while (1) { int sock_com; if ((sock_com = accept(sock_serv, NULL, NULL)) == -1) { perror(" Serveur : erreur sur Accept"); continue; } /* gestion de la communication */ GereComm(sock_com); close(sock_com); } }