Boîte aux lettres fonctionnel même hors localhost. Ajout de nombreux commentaires dans puit.c.

This commit is contained in:
Yohan Boujon 2023-01-24 16:11:16 +01:00
parent 5b9b17b50a
commit a5180da73f
5 changed files with 145 additions and 56 deletions

View file

@ -66,6 +66,20 @@ void receptionEmetteur(int sock, int tailleMessagePrevu, int * tailleMessageRecu
* @param recepteur int, id du recepteur. * @param recepteur int, id du recepteur.
* @param boiteAuxLettres struct listeBAL, la boite aux lettres à renvoyer. * @param boiteAuxLettres struct listeBAL, la boite aux lettres à renvoyer.
*/ */
void receptionRecepteur(int sock, int recepteur, struct listeBAL boiteAuxLettres); int receptionRecepteur(int sock, int socketType, struct sockaddr_in socketStruct, int port, int recepteur, struct listeBAL boiteAuxLettres);
/**
* @brief Permet, à partir de isTCP de choisir la méthode d'envoi.
*
* @param sock int,socket premettant d'utiliser la primitive read()/recvfrom().
* @param socketStruct struct sockaddr_in, la structure du socket avec l'ip et le port.
* @param longueurRecu int, sizeof(socketStruct)
* @param messageRecu char*, la chaîne de caractère qui recevra le message, doit être allouée
* @param tailleMessage int, la longueur donnée par l'utilisateur
* @param isTCP int, 1 -> TCP, 0 -> UDP
* @param i int, fonctionne comme un count pour le printf()
* @return int, renvoi la longueur n reçue par TCP/UDP.
*/
int readRecvFrom(int sock, struct sockaddr_in socketStruct, int longueurRecu, char * messageRecu, int tailleMessage, int isTCP, int i);
#endif #endif

View file

@ -174,7 +174,7 @@ int protocol2int(char * data, int offset);
* @param socketStruct struct sockaddr_in, structure du socket * @param socketStruct struct sockaddr_in, structure du socket
* @param tailleSocket int, sizeof(socketStruct) * @param tailleSocket int, sizeof(socketStruct)
*/ */
void connectTCP(int sock, struct sockaddr_in socketStruct, int tailleSocket); int connectTCP(int sock, struct sockaddr_in socketStruct, int tailleSocket);
/** /**
* @brief Récupère la longueur émise par la fonction write() (TCP) ou sendto() (UDP) * @brief Récupère la longueur émise par la fonction write() (TCP) ou sendto() (UDP)
@ -202,4 +202,23 @@ void printAndVerif(char * sendingMessage,int tailleMessage,int longueurEmis, int
*/ */
int initSocket(int socketType, struct sockaddr_in * socketStruct, int port, char * ipAddress); int initSocket(int socketType, struct sockaddr_in * socketStruct, int port, char * ipAddress);
/**
* @brief Ouvre un socket à l'aide d'un socketType
*
* @param socketType SOCK_STREAM pour TCP ou SOCK_DGRAM pour UDP
* @return int le socket créé
*/
int openSocket(int socketType);
/**
* @brief utilise la fonction listen et accept de TCP pour créer un nouveau socket.
*
* @param sock int, le socket pour lancer la connexion.
* @param socketStruct struct sockaddr_in*, la structure du socket sous forme de pointeur.
* @param sizeSocketStruct int, sizeof(*socketStruct)
* @param closeSocket bool, 1-> ferme le socket sock.
* @return int, le socket crée par accept().
*/
int listenAndAccept(int sock, struct sockaddr_in * socketStruct, int * sizeSocketStruct, bool closeSocket);
#endif #endif

View file

@ -4,13 +4,17 @@ int launchPuit(int nombreMessage,int tailleMessage,int isTCP,int port,char * ipA
{ {
int sock,socketType; int sock,socketType;
struct sockaddr_in socketPuit; struct sockaddr_in socketPuit;
/*socketType change de valeur en fonction de isTCP -> si isTCp alors SOCK_STREAM, sinon SOCK_DGRAM*/
socketType = (isTCP) ? SOCK_STREAM : SOCK_DGRAM; socketType = (isTCP) ? SOCK_STREAM : SOCK_DGRAM;
/*Si le mode boîte aux lettres est activé alors on entre dans le mode BAL -> on return 0 car nous ne voulons pas
rentrer dans le mode TCP/UDP normal.*/
if(isBAL) if(isBAL)
{ {
printf("Mode Boîte aux Lettres\n"); printf("Mode Boîte aux Lettres\n");
modeBoiteAuxLettres(socketPuit,socketType,port,ipAddress); modeBoiteAuxLettres(socketPuit,SOCK_STREAM,port,ipAddress);
return 0; return 0;
} }
/*Sinon on initialise le socket de base et on rentre dans receiveMultipleData() -> on ferme le socket avant*/
sock = initSocket(socketType,&socketPuit,port,ipAddress); sock = initSocket(socketType,&socketPuit,port,ipAddress);
receiveMultipleData(nombreMessage,tailleMessage,sock,socketPuit,isTCP); receiveMultipleData(nombreMessage,tailleMessage,sock,socketPuit,isTCP);
close(sock); close(sock);
@ -19,17 +23,20 @@ int launchPuit(int nombreMessage,int tailleMessage,int isTCP,int port,char * ipA
void modeBoiteAuxLettres(struct sockaddr_in socketStruct, int socketType, int port, char * ipAddress) void modeBoiteAuxLettres(struct sockaddr_in socketStruct, int socketType, int port, char * ipAddress)
{ {
/*Init : Création de la boite aux lettres, de paramRecu pour la couche protocolaire.
Intiialisation de la taille de socketStruct pour les différentes fonctions.
Création des 4 variables à récupérer dans la couche protocolaire.*/
struct listeBAL boiteAuxLettres = initListeBAL(); struct listeBAL boiteAuxLettres = initListeBAL();
char paramRecu[13]; char paramRecu[13];
int n, longueurRecu = sizeof(socketStruct),sock,oldSock, trueTemp = 1,option=1; int n, longueurRecu = sizeof(socketStruct),sock,oldSock;
int param,emetteurRecepteur,tailleMessage,nbMessage; int param,emetteurRecepteur,tailleMessage,nbMessage;
while(1) while(1)
{ {
/*Etat d'attente -> création d'un socket pour écouter le premier client et récupérer son IP. n=1 pour rentrer dans le while*/
n=1; n=1;
oldSock = initSocket(socketType,&socketStruct,port,ipAddress); oldSock = initSocket(socketType,&socketStruct,port,ipAddress);
listen(oldSock,5); sock = listenAndAccept(oldSock,&socketStruct,&longueurRecu,true);
sock = accept(oldSock,(struct sockaddr *)&socketStruct,(socklen_t * restrict)&longueurRecu); /*Tant qu'on reçoit des données, on vérifie si le client nous demande une reception ou une emission*/
close(oldSock);
while(n>0) while(n>0)
{ {
n = read(sock,paramRecu,13); n = read(sock,paramRecu,13);
@ -37,18 +44,8 @@ void modeBoiteAuxLettres(struct sockaddr_in socketStruct, int socketType, int po
switch(param) switch(param)
{ {
case MODE_RECEPTEUR: case MODE_RECEPTEUR:
close(sock); /*On récupère le socket créé par receptionRecepteur pour le fermer par la suite*/
if((sock=socket(AF_INET,socketType,0)) == -1) sock=receptionRecepteur(sock,socketType,socketStruct,port,emetteurRecepteur,boiteAuxLettres);
{
perror("[tsock] : fonction socket() : echec creation du socket\n");
exit(EXIT_FAILURE);
}
initStructSocket(&socketStruct,1,port,ipAddress);
/*On attend 1 seconde pour que la source lance un listen TCP*/
sleep(1);
/*On lance une connexion TCP et on envoit à l'aide de receptionRecepteur() les données*/
connectTCP(sock,socketStruct,sizeof(socketStruct));
receptionRecepteur(sock,emetteurRecepteur,boiteAuxLettres);
/*Pour fermer le while on met n=-1*/ /*Pour fermer le while on met n=-1*/
n=-1; n=-1;
break; break;
@ -60,25 +57,46 @@ void modeBoiteAuxLettres(struct sockaddr_in socketStruct, int socketType, int po
break; break;
} }
} }
/*Si on est en mode emis, le serveur affiche les données rentrées dans la boite aux lettres*/
if(param == MODE_EMIS) if(param == MODE_EMIS)
{ {
afficheListeBAL(boiteAuxLettres); afficheListeBAL(boiteAuxLettres);
} }
/*On ferme le socket qu'il provienne du MODE_RECEPTEUR ou MODE_EMIS*/
close(sock); close(sock);
} }
} }
void receptionRecepteur(int sock, int recepteur, struct listeBAL boiteAuxLettres) int receptionRecepteur(int sock, int socketType, struct sockaddr_in socketStruct, int port, int recepteur, struct listeBAL boiteAuxLettres)
{ {
/*StripAddressStruct va convertir l'adresse de socketStruct en char* car initStructSocket demande ce type de variable.
On crée des pointeurs vers les éléments du recepteur concerné.
inet_ntop permet de convertir une adresse in_addr en char**/
int longueurEmis,i=1; int longueurEmis,i=1;
char *paramMessage; char *paramMessage,StripAddressStruct[INET_ADDRSTRLEN];
struct in_addr ipAddressStruct = ((struct sockaddr_in*)&socketStruct)->sin_addr;
struct elementMessage *elementFinal = getMessages(boiteAuxLettres,recepteur)->fin,*elementCourant = getMessages(boiteAuxLettres,recepteur)->courant;
inet_ntop( AF_INET, &ipAddressStruct, StripAddressStruct, INET_ADDRSTRLEN );
/*On ferme la connexion qui était en mode listen()
On crée un nouveau socket en initialisant la structure sockaddr_in avec l'adresse IP du client*/
close(sock);
sock=openSocket(socketType);
initStructSocket(&socketStruct,1,port,StripAddressStruct);
/*On attend 1 seconde pour que la source lance un listen TCP
On lance une connexion TCP -> Si -1 alors on retourne le socket crée et on ferme la connexion (on retourne dans l'état d'attente)*/
sleep(1);
if (connectTCP(sock,socketStruct,sizeof(socketStruct)) == -1)
{
return sock;
}
printf("\n--- Messages à renvoyer pour %d : ---\n",recepteur); printf("\n--- Messages à renvoyer pour %d : ---\n",recepteur);
struct elementMessage * elementFinal = getMessages(boiteAuxLettres,recepteur)->fin; /*Tant qu'il reste des éléments dans la liste on envoi les différents paquets :
struct elementMessage * elementCourant = getMessages(boiteAuxLettres,recepteur)->courant; La couche protocolaire avec MODE_RECEPTEUR, l'id de celui qui a envoyé le message, la taille et le nombre de messages
Le message avec la taille correcte. On incrémente i pour l'affichage et on passe à l'élément suivant.*/
while(elementCourant->suiv != elementFinal->suiv) while(elementCourant->suiv != elementFinal->suiv)
{ {
paramMessage = formatTextParam(MODE_RECEPTEUR,recepteur,elementCourant->messageBALActuel->tailleData,getMessages(boiteAuxLettres,recepteur)->nbMessages); paramMessage = formatTextParam(MODE_RECEPTEUR,recepteur,elementCourant->messageBALActuel->tailleData,getMessages(boiteAuxLettres,recepteur)->nbMessages);
printf("paramMessage [%d] = %s\n",i,paramMessage);
longueurEmis = write(sock,paramMessage,13); longueurEmis = write(sock,paramMessage,13);
printAndVerif(paramMessage,13,longueurEmis,i); printAndVerif(paramMessage,13,longueurEmis,i);
@ -87,12 +105,16 @@ void receptionRecepteur(int sock, int recepteur, struct listeBAL boiteAuxLettres
i++; i++;
elementCourant=elementCourant->suiv; elementCourant=elementCourant->suiv;
} }
return sock;
} }
void receptionEmetteur(int sock, int tailleMessagePrevu, int * tailleMessageRecu, int emetteur, int recepteur, struct listeBAL *boiteAuxLettres) void receptionEmetteur(int sock, int tailleMessagePrevu, int * tailleMessageRecu, int emetteur, int recepteur, struct listeBAL *boiteAuxLettres)
{ {
/*On créer un pointeur char car nouveauMessage utilise ce dernier pour l'associer à la boite aux lettres*/
char * messageRecu = malloc(sizeof(char)*tailleMessagePrevu); char * messageRecu = malloc(sizeof(char)*tailleMessagePrevu);
/*On lit les messages reçus après chaque envoi protocolaire -> la taille est donc connue*/
*tailleMessageRecu = read(sock,messageRecu,tailleMessagePrevu); *tailleMessageRecu = read(sock,messageRecu,tailleMessagePrevu);
/*Le nouveau message n'est mis dans la BAL que si la donnée est correcte : donc au dessus d'une taille de 0 octet*/
if(*tailleMessageRecu>0) if(*tailleMessageRecu>0)
{ {
nouveauMessage(boiteAuxLettres,emetteur,recepteur,messageRecu); nouveauMessage(boiteAuxLettres,emetteur,recepteur,messageRecu);
@ -101,45 +123,48 @@ void receptionEmetteur(int sock, int tailleMessagePrevu, int * tailleMessageRecu
int receiveMultipleData(int nombreMessages, int tailleMessage, int sock, struct sockaddr_in socketStruct, int isTCP) int receiveMultipleData(int nombreMessages, int tailleMessage, int sock, struct sockaddr_in socketStruct, int isTCP)
{ {
/*messageRecu sera affiché avec un printf. La variable count est créé au préalable pour le while, n est mis à 1 pour la même raison*/
char messageRecu[tailleMessage+1]; char messageRecu[tailleMessage+1];
int n=1, longueurRecu = sizeof(socketStruct); int n=1, count=0, longueurRecu = sizeof(socketStruct);
/*Dans le cas d'une connexion TCP on lance la primitive listenAndAccept() pour établir la connexion avec la source/le client*/
if(isTCP) if(isTCP)
{ {
listen(sock,5); sock = listenAndAccept(sock,&socketStruct,&longueurRecu,true);
sock = accept(sock,(struct sockaddr *)&socketStruct,(socklen_t * restrict)&longueurRecu);
} }
/*On reçoit des messages tant qu'ils sont vide (pour TCP uniquement)*/
if(nombreMessages < 0) if(nombreMessages < 0)
{ {
int i=1; /*Tant qu'on reçoit des messages on continue.*/
while(n>0) while(n>0)
{ {
if(isTCP) n=readRecvFrom(sock,socketStruct,longueurRecu,messageRecu,tailleMessage,isTCP,count+1);
{ count++;
n = read(sock,messageRecu,tailleMessage);
}
else
{
n = recvfrom(sock, (char *)messageRecu, tailleMessage, 0, (struct sockaddr*) &socketStruct,(socklen_t *__restrict__)&longueurRecu);
}
messageRecu[n] = '\0';
printf("Puit\tReception n°%d (%d) :\t[%s]\n",i,n,messageRecu);
i++;
} }
} }
else{ else{
for(int i=0;i<nombreMessages;i++) /*On lit un certain nombre de message donné par l'utilisateur*/
for(count=0;count<nombreMessages;count++)
{ {
if(isTCP) n=readRecvFrom(sock,socketStruct,longueurRecu,messageRecu,tailleMessage,isTCP,count+1);
{
n = read(sock,messageRecu,tailleMessage);
}
else
{
n = recvfrom(sock, (char *)messageRecu, tailleMessage, 0, (struct sockaddr*) &socketStruct,(socklen_t *__restrict__)&longueurRecu);
}
messageRecu[n] = '\0';
printf("Puit\tReception n°%d (%d) :\t[%s]\n",i+1,tailleMessage,messageRecu);
} }
} }
return 0; return 0;
} }
int readRecvFrom(int sock, struct sockaddr_in socketStruct, int longueurRecu, char * messageRecu, int tailleMessage, int isTCP, int i)
{
int n;
/*Pour TCP on utilise read(), pour UDP recvfrom()*/
if(isTCP)
{
n = read(sock,messageRecu,tailleMessage);
}
else
{
n = recvfrom(sock, (char *)messageRecu, tailleMessage, 0, (struct sockaddr*) &socketStruct,(socklen_t *__restrict__)&longueurRecu);
}
/*On ajoute \0 en fin de chaîne pour l'afficher correctement sur la console.*/
messageRecu[n] = '\0';
printf("Puit\tReception n°%d (%d) :\t[%s]\n",i,n,messageRecu);
return n;
}

View file

@ -88,9 +88,7 @@ void modeRecepteur(int recepteur,int sock,struct sockaddr_in * socketStruct,int
close(sock); close(sock);
oldSock = initSocket(SOCK_STREAM,socketStruct,port,ipAddress); oldSock = initSocket(SOCK_STREAM,socketStruct,port,ipAddress);
listen(oldSock,5); sock = listenAndAccept(oldSock,socketStruct,&tailleSocketStruct,true);
sock = accept(oldSock,(struct sockaddr *)&socketStruct,(socklen_t * restrict)&tailleSocketStruct);
close(oldSock);
while(i<nbMessage) while(i<nbMessage)
{ {
longueurEmis = read(sock,paramRecu,13); longueurEmis = read(sock,paramRecu,13);
@ -100,4 +98,5 @@ void modeRecepteur(int recepteur,int sock,struct sockaddr_in * socketStruct,int
printAndVerif(messageRecu,tailleMessage,longueurEmis,i); printAndVerif(messageRecu,tailleMessage,longueurEmis,i);
i++; i++;
} }
close(sock);
} }

View file

@ -152,13 +152,14 @@ int protocol2int(char * data, int offset)
return atoi(buff)%10000; return atoi(buff)%10000;
} }
void connectTCP(int sock, struct sockaddr_in socketStruct, int tailleSocket) int connectTCP(int sock, struct sockaddr_in socketStruct, int tailleSocket)
{ {
if(connect(sock,(struct sockaddr *)&socketStruct,(socklen_t)tailleSocket) == -1) int returnConnect = connect(sock,(struct sockaddr *)&socketStruct,(socklen_t)tailleSocket);
if(returnConnect == -1)
{ {
perror("[tsock] : fonction connect() : echec connexion\n"); perror("[tsock] : fonction connect() : echec connexion\n");
exit(EXIT_FAILURE);
}; };
return returnConnect;
} }
void printAndVerif(char * sendingMessage,int tailleMessage,int longueurEmis, int count) void printAndVerif(char * sendingMessage,int tailleMessage,int longueurEmis, int count)
@ -189,3 +190,34 @@ int initSocket(int socketType, struct sockaddr_in * socketStruct, int port, char
} }
return sockReturn; return sockReturn;
} }
int openSocket(int socketType)
{
int returnSock;
if((returnSock=socket(AF_INET,socketType,0)) == -1)
{
perror("[tsock] : fonction socket() : echec creation du socket\n");
exit(EXIT_FAILURE);
}
return returnSock;
}
int listenAndAccept(int sock, struct sockaddr_in * socketStruct, int * sizeSocketStruct, bool closeSocket)
{
int listenStatus;
listenStatus = listen(sock,5);
if(listenStatus < 0)
{
perror("[tsock] : listen() failed.");
}
int returnSock = accept(sock,(struct sockaddr *)socketStruct,(socklen_t * restrict)sizeSocketStruct);
if(returnSock < 0)
{
perror("[tsock] : accept() failed.");
}
if(closeSocket)
{
close(sock);
}
return returnSock;
}