|
Membre du Club
Flo Inscription : juin 2009 Messages : 88 Détails du profil  Informations personnelles : Nom : Flo Informations forums :
Inscription : juin 2009 Messages : 88 Points : 69 Points : 69
|
Blocage recvmsg (client/serveur udp)
Bonjour à tous,
Voilà je dispose d'un client et d'un serveur (appelés émetteur et receveur).
Grosso modo :
l'émetteur envoie un fichier texte au receveur. Après chaque paquet envoyé, il attend la réception d'un ack.
le receveur attend des paquets. a chaque paquet reçu il envoie un ack
Mon problème est que je reste bloqué sur l'émetteur après l'appel à la fonction reception()
CODE DE l'EMETTEUR
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
/*******************************************************
Nom ......... : emetteur.c
Role ........ : Client UDP
Compilation :
make all
********************************************************/
#include "librairies.h"
#include "socket.h"
#define DEBUG_MODE
int main (int argc, char *argv[])
{
/*Variables*/
int emetteur;/*Descripteur de la socket*/
char bufenvoi[MAX_BUF]; int ret_envoi; /**/
char bufreception[MAX_BUF]; int ret_reception; /**/
char ligne[MAX_BUF];/*Ligne (du fichier) en cours d'envoi au récepteur*/
int error;
struct sockaddr_in receveur;/**/
struct in_addr *ip_receveur;/**/
struct hostent *h; /*Utilisé pour la resolution des noms de domaine (DNS)*/
FILE *fichier=fopen("fichier_demo.txt", "r");/*Pointeur vers le fichier que l'on va envoyer au récepteur*/
/*Contrôle du nombre d'arguments*/
if (argc != 3)
{
printf("\nUsage: ./%s IPrecepteur NumPort\n", argv[0]);
exit(1);
}
/*Création de la socket de l'émetteur*/
emetteur = creeSocket(atoi(argv[2]));
if(emetteur<0)
{
perror("Erreur création socket");
}
/*Construction de l'adresse du récepteur*/
receveur.sin_family = AF_INET;
receveur.sin_port = htons(SERVEUR_PORT);
h = gethostbyname(argv[1]);
if (h == NULL)
{
perror("Erreur gethostbyname\n");
exit(1);
}
ip_receveur = (struct in_addr *)h->h_addr_list[0];
printf("\n Adresse ip du receveur est: %s\n",inet_ntoa(*ip_receveur));
inet_ntoa(*ip_receveur);
memcpy((char*)(&receveur.sin_addr.s_addr), h->h_addr_list[0], h->h_length);
/*Envoi du fichier au récepteur*/
while(fgets(ligne,MAX_BUF,fichier)!=NULL)
{
/*On note ici que le seul changement par rapport à un envoi UDP "classique" est l'appel à la fonction "envoi" au lieu de "sendto"*/
if (envoi(emetteur,ligne,strlen(ligne),0,(struct sockaddr_in *)&receveur, sizeof(receveur)) < 0)
{
perror (argv[0]);
exit(1);
}
else
{
printf("Envoi à %s sur le port %d:\n",inet_ntoa(receveur.sin_addr),receveur.sin_port);
printf("%s\n",ligne);
/*Tentative de réception d'un ack*/
reception (emetteur, bufreception, MAX_BUF, 0, (struct sockaddr_in *)&receveur, sizeof(receveur));
/*printf("Reçu %s\n", bufreception);*/
}
}
/*Fermeture de la socket et du fichier*/
close (emetteur);
fclose(fichier);
return 0;
} |
CODE DU RECEVEUR :
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
/*******************************************************
Nom ......... : Serveur.c
Role ........ : Serveur UDP
Compilation :
make all
********************************************************/
#include "librairies.h"
#include "socket.h"
#define DEBUG_MODE
int main(int argc, char *argv[])
{
/*Variables*/
int receveur; /*descripteur du socket du receveur*/
char bufreception[MAX_BUF]; int ret_reception;/*pour la réception de paquets*/
char bufenvoi[MAX_BUF]; int ret_envoi;/*pour l'envoi de paquets*/
struct sockaddr_in emetteur;/*adresse de l'émetteur (client qui viendra se connecter)*/
time_t temps;/*stockage d'une date*/
FILE *log;
strncpy(bufreception,"",strlen(bufreception)) ;
/*Contrôle du nombre d'arguments*/
if (argc != 2)
{
printf("\nUsage: ./%s numPort\n", argv[0]);
exit(1);
}
/*Construction fichier de log*/
log=fopen("log.txt","w+");
if(log==NULL)
{
perror("Erreur d'accès au fichier 'log.txt', l'archivage sur cette session n'est pas géré\n");
}
time(&temps);
fprintf(log," -------------------------------------------------\n");
fprintf(log,"| Ce fichier contient l'historique des connexions |\n");
fprintf(log," -------------------------------------------------\n");
fprintf(log," Date de creation: %s \n ", ctime(&temps));
/*Création de la socket du receveur*/
receveur=creeSocket(atoi(argv[1]));
fprintf(log, "Creation d'une socket sur le port %d... \n",atoi(argv[1]));
#ifdef DEBUG_MODE
printf("Creation d'une socket sur le port %d... \n",atoi(argv[1]));
#endif
/*Boucle infinie de réception des messages de l'émetteur*/
while(1)
{
fflush(stdout);
ret_reception=reception(receveur, bufreception,MAX_BUF,0, (struct sockaddr_in*)&emetteur, sizeof(emetteur));
if (ret_reception<0)
{
perror("Erreur réception du paquet\n");
exit(1);
}
/*Récupération des infos de l'émetteur*/
printf("Réception d'un message de : %s:%u\n",inet_ntoa(emetteur.sin_addr),ntohs(emetteur.sin_port));
time(&temps);
fprintf(log, "\n Une demande de connexion est recue:\n");
fprintf(log, "\t * Date de connexion: %s", ctime(&temps));
fprintf(log, "\t * Famille du Socket client: %x\n", ntohs(emetteur.sin_family));
fprintf(log, "\t * Port client: %u\n", ntohs(emetteur.sin_port));
fprintf(log, "\t * IP client: %s\n", inet_ntoa(emetteur.sin_addr));
/*Traitement du paquet reçu*/
printf("Contenu du paquet :\n\t%s\n",bufreception);
fprintf(log, "Contenu du paquet : \n");
fprintf(log, "\t%s\n",bufreception);
/*Réinitialisation du buffer de réception*/
strncpy(bufreception,"",strlen(bufreception)) ;
strncpy(bufenvoi,"hi",strlen(bufenvoi)) ;
sleep(3);/*Pour test*/
envoi(receveur,bufenvoi,MAX_BUF,0,(struct sockaddr_in*)&emetteur, sizeof(emetteur));
}
/*Fermeture des sockets/fichiers ouverts*/
fclose(log);
close(receveur);
return 0;
} |
CODE DES FONCTIONS ENVOI/RECEPTION
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
#include "rtt.h"
#include "socket.h"
#define DEBUG_MODE
/*Variables*/
uint32_t recentsequence; /*Dernier numéro de séquence acquitté*/
static struct msghdr msgenvoi, msgreception; /*Structure despaquets à envoyer/recevoir*/
static struct header { /*Structure des informations complémentaires à joindre dans nos paquets*/
int type; /*0 pour les data, 1 pour les ack*/
uint32_t sequence; /*Numéro de séquence*/
uint32_t ack; /*Acquittement du dernier numéro de séquence reçu*/
/*uint32_t ack_precedents; Bits d'acquittements des 32 derniers paquets*/
} envoihdr, receptionhdr;
/*Fin déclaration variables*/
/*Fonction d'envoi d'un paquet de manière fiable que send*/
ssize_t envoi(int sockfd, void *buf, size_t len, int flags, struct sockaddr_in *dest_addr, socklen_t addrlen)
{
int n;/*retour de la fonction 'sendmsg'*/
/*Phase 1 : Préparation des nouvelles données du paquet constituées du nouvel header et des données à envoyer*/
struct iovec iovenvoi[2];/*Une structure iovec va être remplie avec : - Un pointeur vers des données, - La taille de ces données*/
iovenvoi[0].iov_base=&envoihdr;/*pointeur vers données[0] : intégration du nouvel header*/
iovenvoi[0].iov_len=sizeof(struct header);/*taille des données[0] : taille du nouvel header*/
iovenvoi[1].iov_base=buf;/*pointeur vers données[1] : intégration des données à envoyer*/
iovenvoi[1].iov_len=len;/*taille des données[1] : taille des données*/
/*Remplissage du header*/
envoihdr.sequence++;
envoihdr.type=0;
envoihdr.ack=recentsequence;
/*Phase 2 : Création d'un nouveau paquet*/
msgenvoi.msg_name=dest_addr;
msgenvoi.msg_namelen=addrlen;
/*Phase 3 : Intégration des données au paquet*/
msgenvoi.msg_iov=iovenvoi;
msgenvoi.msg_iovlen=2;
#ifdef DEBUG_MODE
fprintf(stderr, "\nEnvoi du paquet :%4d\n",envoihdr.sequence);
#endif
n=sendmsg(sockfd, &msgenvoi,0);
return (n-sizeof(struct header));
}
/*Fonction de réception d'un paquet de manière plus fiable que recv*/
ssize_t reception(int sockfd, void *buf, size_t len, int flags, struct sockaddr_in *src_addr, socklen_t *addrlen)
{
/*Variables*/
ssize_t n;
struct iovec iovreception[2];
/*select*/
int ret = 0;
fd_set readfs;
char* msgbufreception;
/*Préparation du paquet*/
msgreception.msg_name=NULL;
msgreception.msg_namelen=0;
msgreception.msg_iov=iovreception;
msgreception.msg_iovlen=2;
iovreception[0].iov_base=&receptionhdr;
iovreception[0].iov_len=sizeof(struct header);
iovreception[1].iov_base=buf;
iovreception[1].iov_len=len;
n=recvmsg(sockfd,&msgreception,0);
#ifdef DEBUG_MODE
fprintf(stderr, "Reçu paquet num séquence :%4d\n", receptionhdr.sequence);
#endif
/*Comparaison du numéro de séquence du paquet reçu avec la variable recentsequence, et mise à jour de cette variable si nécessaire*/
if(receptionhdr.sequence > recentsequence)
{
recentsequence=receptionhdr.sequence;
}
return(n - sizeof(struct header));/*Retourne la taille du datagramme reçu*/
} |
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
int creeSocket(int numPort)
{
struct sockaddr_in servAddr;
int sd; /*descripteur du socket*/
int reuse=1;
/*Création de la socket*/
if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Erreur création de socket\n");
exit(1);
}
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(numPort);
/*Attachement de la socket à une addresse et un port*/
if (bind(sd,(struct sockaddr*) &servAddr, sizeof(servAddr)) < 0)
{
perror("Erreur bind socket\n");
exit(1);
}
/*Pour libération de la socket après close()*/
if(setsockopt(sd,SOL_SOCKET, SO_REUSEADDR, (int *)&reuse, sizeof(reuse))==-1) {
perror("Erreur SO_REUSEADDR");
}
#ifdef DEBUG_MODE
printf("Socket créée\n");
#endif
return sd;
} |
|