482 lines
13 KiB
C
482 lines
13 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/un.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
#include <unistd.h>
|
|
|
|
void construire_message(char *message, char motif, int lg) {
|
|
int i;
|
|
for (i=0; i<(lg); i++) {
|
|
message[i] = motif;
|
|
}
|
|
}
|
|
|
|
void afficher_message(char *message, int lg, int num) {
|
|
int i;
|
|
printf("n°%d (%d) [----%d", num, lg, num);
|
|
for (i=0; i<lg; i++) {
|
|
printf("%c", message[i]);
|
|
}
|
|
printf("]\n");
|
|
}
|
|
|
|
void usage() {
|
|
printf("usage: cmd [-h] [-p|-s] [-c] [-e|-r] [-u|-t] [-n ##] [-l ##] <url_correspondant> <num_port> \n");
|
|
printf(" -h : help (prints this message)\n");
|
|
printf(" -p : puit (uniquement pour serveur en tcp)\n");
|
|
printf(" -s : source (uniquement pour serveur en tcp)\n");
|
|
printf(" -c : client (uniquement en tcp)\n");
|
|
printf(" -e : émetteur (uniquement si client tcp)\n");
|
|
printf(" -r : recepteur (uniquement si client tcp)\n");
|
|
printf(" -u : protocole UDP\n");
|
|
printf(" -t : protocole TCP\n");
|
|
printf(" -n ## : indique le nombre de messages à envoyer\n");
|
|
printf(" -l ## : longeur de chaqu'un des messages à envoyer\n");
|
|
}
|
|
|
|
|
|
int main (int argc, char **argv) {
|
|
int i; // pour les boucles for
|
|
int c; // pour getopt
|
|
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 transport = -1 ; /* 0=UDP, 1=TCP <- par défaut*/
|
|
int client = 0; /* 0=client, 1=serveur */
|
|
int recepteur = -1; /* 0=éméteur, 1=recepteur (pour un client) */
|
|
|
|
struct hostent *hp;
|
|
struct sockaddr_in adr_em;
|
|
struct sockaddr_in adr_local;
|
|
struct sockaddr_in adr_distant;
|
|
|
|
int sock;
|
|
int sock_bis;
|
|
int port;
|
|
|
|
unsigned int lg_adr_em=sizeof(adr_em);
|
|
int lg_adr_local=sizeof(adr_local);
|
|
int lg_adr_dest=sizeof(adr_distant);
|
|
int lg_mesg = 30;
|
|
int lg_max = 30;
|
|
int nb_max_connexion = 5;
|
|
int count = 0; // compte le nombre de messages transmis
|
|
char* pmesg;
|
|
|
|
|
|
printf("début père\n");
|
|
|
|
while ((c = getopt(argc, argv, "hpscertun:l:")) != -1) {
|
|
switch (c) {
|
|
case 'h':
|
|
usage();
|
|
return 0;
|
|
case 'c': /* Si on est en mode tcp, on devient client */
|
|
if (transport && ( source == 1 || source == 0) ) { /* on ne peut pas être client et serveur à la fois */
|
|
usage();
|
|
exit(1);
|
|
}
|
|
client = 1;
|
|
break;
|
|
case 'e': /* Client emetteur */
|
|
if (recepteur == 1 || client != 1) {
|
|
usage();
|
|
exit(1);
|
|
}
|
|
recepteur = 0;
|
|
break;
|
|
case 'r': /* Client recepteur */
|
|
if (recepteur == 0 || client != 1) {
|
|
usage();
|
|
exit(1);
|
|
}
|
|
recepteur = 1;
|
|
break;
|
|
case 'p': /* On choisit le puit. */
|
|
if (source == 1) {
|
|
usage();
|
|
exit(1);
|
|
}
|
|
source = 0;
|
|
break;
|
|
|
|
case 's': /* On choisit la source. */
|
|
if (source == 0) {
|
|
usage();
|
|
exit(1) ;
|
|
}
|
|
source = 1;
|
|
break;
|
|
|
|
case 'u': /* On choisit le mode UDP. */
|
|
if (transport == 1) {
|
|
usage();
|
|
exit(1);
|
|
}
|
|
transport = 0;
|
|
break;
|
|
|
|
case 't': /* On choisit le mode TCP */
|
|
if (transport == 0) {
|
|
usage();
|
|
exit(1);
|
|
}
|
|
transport = 1;
|
|
break;
|
|
|
|
case 'n': /* On choisit le nombre de messages à envoyer ou à lire. */
|
|
nb_message = atoi(optarg);
|
|
break;
|
|
|
|
case 'l': /* On choisit la longueur des messages à envoyer ou la longueur maximale des messages à lire. */
|
|
lg_mesg = atoi(optarg);
|
|
break;
|
|
|
|
default:
|
|
usage();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (client == 1 && recepteur == -1) { /* Si on est client on doit préciser si on est recepteur ou emetteur */
|
|
usage();
|
|
exit(1);
|
|
}
|
|
|
|
if (transport == -1) { /* Protocole par défault est TCP */
|
|
transport = 1;
|
|
}
|
|
|
|
if (source == -1 && ( (transport == 1 && client == 0) || transport == 0 ) ) {
|
|
usage();
|
|
exit(1) ;
|
|
}
|
|
|
|
if(argc==optind){ /* Il faut préciser le port de la machine vers laquelle on veut se connecter */
|
|
exit(1);
|
|
}
|
|
|
|
if(argc == optind + 2){
|
|
if (source == 0){
|
|
printf("On est dans le puits : nom de machine ignoré\n");
|
|
}
|
|
port = atoi(argv[optind+1]);
|
|
}
|
|
else {
|
|
if (source == 1){
|
|
printf("On est dans la source : il faut un nom de machine et un numéro de port.\n");
|
|
exit(1);
|
|
}
|
|
port = atoi(argv[optind]);
|
|
}
|
|
|
|
|
|
port = htons(port);
|
|
|
|
if (port<5000){
|
|
printf("Le numéro de port doit être supérieur à 5000.\n");
|
|
exit(1);
|
|
}
|
|
|
|
pmesg = malloc(sizeof(char)*lg_mesg);
|
|
|
|
|
|
if (transport==0) { //protocole UDP
|
|
|
|
//---------SOURCE---------//
|
|
if (source == 1) {
|
|
|
|
|
|
if (nb_message == -1) {
|
|
nb_message = 10; // par défaut
|
|
}
|
|
printf("SOURCE : lg_mesg_emis=%d, port=%d, nb_envois=%d, TP=udp, dest=%s\n", lg_mesg, ntohs(port), nb_message, argv[argc-2]);
|
|
|
|
//création du socket local
|
|
if((sock=socket(AF_INET, SOCK_DGRAM,0)) == -1) {
|
|
perror("echec de la creation du socket");
|
|
exit(1);
|
|
}
|
|
printf("SOURCE: socket\n");
|
|
|
|
//construction de l'adresse du socket distant
|
|
//affectation domaine et num port
|
|
memset((char *)&adr_distant, 0, sizeof(adr_distant));
|
|
adr_distant.sin_family=AF_INET;
|
|
adr_distant.sin_port=port;
|
|
|
|
//affectation @IP
|
|
if((hp=gethostbyname(argv[argc-2])) == NULL) {
|
|
perror("erreur gethostbyname");
|
|
exit(1);
|
|
}
|
|
memcpy((char*)&(adr_distant.sin_addr.s_addr), hp->h_addr, hp->h_length);
|
|
|
|
|
|
|
|
if (lg_mesg<6){
|
|
printf("Erreur: la taille du buffer doit être >=6.\n");
|
|
exit(1);
|
|
}
|
|
|
|
//envoi
|
|
for(i=0; i<nb_message; i++) {
|
|
construire_message(pmesg, (char)((i%26)+'a'), lg_mesg);
|
|
printf("SOURCE: Envoi ");
|
|
afficher_message(pmesg, lg_mesg, (i+1));
|
|
sendto(sock, pmesg, lg_mesg, 0,(struct sockaddr*)&adr_distant, lg_adr_dest);
|
|
}
|
|
if (close(sock)==-1) {
|
|
perror("échec de destruction du socket");
|
|
exit(1);
|
|
}
|
|
|
|
printf("SOURCE: fin\n");
|
|
}
|
|
|
|
//---------PUITS---------//
|
|
else {
|
|
|
|
if (nb_message == -1) {
|
|
printf("PUITS : lg_mesg_lu=%d, port=%d, nb_receptions=infini, TP=udp\n", lg_mesg, port);
|
|
} else {
|
|
printf("PUITS : lg_mesg_lu=%d, port=%d, nb_receptions=%d, TP=udp\n", lg_mesg, port, nb_message);
|
|
}
|
|
|
|
//création du socket
|
|
if((sock=socket(AF_INET, SOCK_DGRAM,0)) == -1) {
|
|
perror("echec de la creation du socket");
|
|
exit(1);
|
|
}
|
|
printf("PUITS: socket\n");
|
|
|
|
//construction de l'@ du socket
|
|
memset((char*)&adr_local, 0, sizeof(adr_local));
|
|
adr_local.sin_family=AF_INET;
|
|
adr_local.sin_port=port;
|
|
adr_local.sin_addr.s_addr=INADDR_ANY;
|
|
|
|
//bind
|
|
if (bind(sock,(struct sockaddr*)&adr_local, lg_adr_local) == -1) {
|
|
perror("echec du bind");
|
|
exit(1);
|
|
}
|
|
|
|
int count=0;
|
|
lg_max=lg_mesg;
|
|
|
|
//reception
|
|
/* if (nb_message == -1) { */
|
|
while ((lg_mesg=recvfrom(sock, pmesg, lg_max, 0, (struct sockaddr*)&adr_em, &lg_adr_em)) != -1) {
|
|
printf("PUITS: Reception ");
|
|
count++;
|
|
afficher_message(pmesg, lg_mesg, count);
|
|
|
|
}
|
|
/* } */
|
|
/* else { */
|
|
/* for (int k=0; k<nb_message; k++) { */
|
|
/* if((lg_mesg=recvfrom(sock, pmesg, lg_max, 0, (struct sockaddr*)&adr_em, &lg_adr_em)) != -1) { */
|
|
/* printf("PUITS: Reception "); */
|
|
/* afficher_message(pmesg, lg_mesg, (k+1)); */
|
|
/* } */
|
|
/* } */
|
|
/* } */
|
|
|
|
|
|
if (close(sock)==-1) {
|
|
perror("échec de destruction du socket");
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
else { //connexion TCP
|
|
|
|
//---------Client---------//
|
|
if (client == 1) {
|
|
|
|
if (nb_message ==-1) {
|
|
nb_message = 10;
|
|
}
|
|
|
|
printf("SOURCE : lg_mesg_emis=%d, port=%d, nb_envois=%d, TP=tcp, dest=%s\n", lg_mesg, port, nb_message, argv[argc-2]);
|
|
|
|
//création du socket local
|
|
if((sock=socket(AF_INET, SOCK_STREAM,0)) == -1) {
|
|
perror("échec de la creation du socket");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
//construction de l'adresse du socket distant
|
|
//affectation domaine et num port
|
|
memset((char *)&adr_distant, 0, sizeof(adr_distant));
|
|
adr_distant.sin_family=AF_INET;
|
|
adr_distant.sin_port=port;
|
|
|
|
//affectation @IP
|
|
if((hp=gethostbyname(argv[argc-2])) == NULL) {
|
|
perror("erreur gethostbyname");
|
|
exit(1);
|
|
}
|
|
|
|
memcpy((char*)&(adr_distant.sin_addr.s_addr), hp->h_addr, hp->h_length);
|
|
|
|
printf("SOURCE: socket\n");
|
|
|
|
//connexion
|
|
if (connect(sock,(struct sockaddr*)&adr_distant, lg_adr_dest) == -1) {
|
|
perror("echec de la connexion\n");
|
|
exit(1);
|
|
}
|
|
|
|
printf("SOURCE: connect\n");
|
|
|
|
if (recepteur == 1) {
|
|
lg_max=lg_mesg;
|
|
if (nb_message == -1) {
|
|
int count = 0;
|
|
while ((lg_mesg=recv(sock, pmesg, lg_max, 0))>0) {
|
|
count++;
|
|
printf("PUITS: Reception ");
|
|
afficher_message(pmesg, lg_mesg, count);
|
|
}
|
|
} else {
|
|
for (int k=0; k<nb_message; k++) {
|
|
if ((lg_mesg=recv(sock, pmesg, lg_max, 0))>0) {
|
|
printf("PUITS: Reception ");
|
|
afficher_message(pmesg, lg_mesg, (k+1));
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
//envoi
|
|
for(i=0; i<nb_message; i++) {
|
|
printf("SOURCE: Envoi ");
|
|
construire_message(pmesg, (char)((i%26)+'a'), lg_mesg);
|
|
afficher_message(pmesg, lg_mesg, (i+1));
|
|
send(sock, pmesg, lg_mesg, 0);
|
|
}
|
|
}
|
|
|
|
if (close(sock)==-1) {
|
|
perror("échec de destruction du socket");
|
|
}
|
|
|
|
printf("SOURCE: fin\n");
|
|
|
|
}
|
|
|
|
//---------Serveur---------//
|
|
else {
|
|
|
|
if (nb_message == -1) {
|
|
printf("PUITS : lg_mesg_lu=%d, port=%d, nb_receptions=infini, TP=tcp\n", lg_mesg, port);
|
|
} else {
|
|
printf("PUITS : lg_mesg_lu=%d, port=%d, nb_receptions=%d, TP=tcp\n", lg_mesg, port, nb_message);
|
|
}
|
|
|
|
|
|
//création du socket
|
|
if((sock=socket(AF_INET, SOCK_STREAM,0)) == -1) {
|
|
perror("echec de la creation du socket");
|
|
exit(1);
|
|
}
|
|
|
|
//construction de l'@ du socket
|
|
memset((char*)&adr_local, 0, sizeof(adr_local));
|
|
adr_local.sin_family=AF_INET;
|
|
adr_local.sin_port=port;
|
|
adr_local.sin_addr.s_addr=INADDR_ANY;
|
|
|
|
//bind
|
|
if (bind(sock,(struct sockaddr*)&adr_local, lg_adr_local) == -1) {
|
|
perror("echec du bind");
|
|
exit(1);
|
|
}
|
|
|
|
printf("PUITS : socket\n");
|
|
|
|
//dimensionnement de la file de demandes de connexion
|
|
if (listen(sock, nb_max_connexion) == -1) {
|
|
perror("echec du listen");
|
|
exit(1);
|
|
}
|
|
|
|
while (sock != 0) {
|
|
|
|
//acceptation d'une demande de connexion
|
|
if((sock_bis=accept(sock,(struct sockaddr *)&adr_em, &lg_adr_em)) == -1) {
|
|
perror("echec du accept");
|
|
exit(1);
|
|
}
|
|
|
|
printf("PUITS: connexion acceptée\n");
|
|
|
|
printf("fin père\n");
|
|
switch(fork()) {
|
|
case -1:
|
|
perror("erreur durant le fork\n");
|
|
exit(1);
|
|
break;
|
|
case 0:
|
|
close(sock);
|
|
sock = 0;
|
|
printf("début fils\n");
|
|
if (source == 1) {
|
|
//envoi
|
|
for(i=0; i<nb_message; i++) {
|
|
printf("SOURCE: Envoi ");
|
|
construire_message(pmesg, (char)((i%26)+'a'), lg_mesg);
|
|
afficher_message(pmesg, lg_mesg, (i+1));
|
|
send(sock_bis, pmesg, lg_mesg, 0);
|
|
}
|
|
} else {
|
|
//reception
|
|
lg_max=lg_mesg;
|
|
if (nb_message == -1) {
|
|
count = 0;
|
|
while ((lg_mesg=recv(sock_bis, pmesg, lg_max, 0))>0) {
|
|
count++;
|
|
printf("PUITS: Reception ");
|
|
afficher_message(pmesg, lg_mesg, count);
|
|
}
|
|
} else {
|
|
for (int k=0; k<nb_message; k++) {
|
|
if ((lg_mesg=recv(sock_bis, pmesg, lg_max, 0))>0) {
|
|
printf("PUITS: Reception ");
|
|
afficher_message(pmesg, lg_mesg, (k+1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
if (close(sock_bis) == -1) {
|
|
perror("Echec lors de la destruction du socket_bis");
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (sock != 0) {
|
|
printf("début père\n");
|
|
} else {
|
|
printf("fin fils\n");
|
|
}
|
|
}
|
|
if (close(sock)==-1) {
|
|
perror("Échec de destruction du socket\n");
|
|
exit(1);
|
|
}
|
|
|
|
printf("PUITS: fin\n");
|
|
}
|
|
}
|
|
free(pmesg);
|
|
printf("fin père\n");
|
|
}
|