IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Communication serveur/client : envoi d'accusé de réception


Sujet :

Réseau C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 19
    Points : 28
    Points
    28
    Par défaut Communication serveur/client : envoi d'accusé de réception
    Bonjour à tous,

    je me permets de vous déranger pour vous poser une question concernant l'envoi d'accusés de réception par un serveur.
    En Licence 3 Informatique, nous devons coder un petit serveur et un petit client permettant simplement d'envoyer un message (du client vers le serveur) puis d'envoyer un accusé de réception à ce même client. Or, si la première partie fonctionne, la deuxième a tendance à planter...

    Code du client :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #define Internet_Port 2074
    #define TAILLE_MAX_MSG 256
    /*
    Programme client en mode connecté : échange de séquences de caractères continues et non structurées
    */
    main(argc,argv)
    int argc;
    char **argv;
    {
    	int sd, lon, nsr;
    	struct sockaddr_in adsock;
    	struct hostent *hptr;
    	struct servent *sptr;
    	char buf[13];
    	char *prog;
    	char *host;
    	char mesg[8]="BONJOUR";
    	prog = argv[0];
    	if(argc!=2)
    	{
    		perror("Il faut un argument");
    		exit(1);
    	}
    	host=argv[1];
    	//Infos du host
    	if((hptr=gethostbyname(host))==NULL)
    	{
    		perror("Probleme Info sur le host");
    		exit(1);
    	}
    	/*
    	Initialiser le adsock avec les infos du host pour préparer adresse d'attachement
    	*/
    	bcopy((char *)hptr->h_addr,(char *)&adsock.sin_addr.s_addr,hptr->h_length);
    	adsock.sin_family=hptr->h_addrtype;
    	//récupération du numéro de port
    	adsock.sin_port = htons(Internet_Port);
    	//création du socket
    	if((sd=socket(AF_INET,SOCK_STREAM,0))<0)
    	{
    		perror("Erreur lors de la creation du socket");
    		close(sd);
    		exit(1);
    	}
    	//connexion serveur
    	if((connect(sd,&adsock,sizeof(adsock)))<0)
    	{
    		perror("Erreur connexion");
    		close(sd);
    		exit(1);
    	}
    	//envoi requête
    	if((write(sd,mesg,8))<0)
    	{
    		perror("Erreur lors de l'ecriture");
    		exit(1);
    	}
    	lon=sizeof(adsock);
    	if((nsr=accept(sd,&adsock,&lon))<0)
    	{
    		close(nsr);
    		perror("Erreur accept");
    		exit(1);
    	}else{
    		recv(nsr,buf,13,0);
    		printf("%s \n",buf);
    		close(nsr);
    	}
    	close(sd);
    	exit(0);
    }
    Code du serveur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #define Internet_Port 2074
    #define TAILLE_MAX_MSG 256
     
    main(int argc, char **argv)
    {
    	int sd, lon, nsd, i, sr;
    	struct sockaddr_in adsock, adacc;
    	struct hostent *hptr;
    	struct servent *sptr;
    	char buf[8];
    	char ack[13]="MESSAGE RECU";
    	char *prog;
    	char *host;
    	prog = argv[0];
    	if(argc!=2)
    	{
    		perror("Il faut un argument");
    		exit(1);
    	}
    	host=argv[1];
    	//Infos du host
    	if((hptr=gethostbyname(host))==NULL)
    	{
    		perror("Probleme Info sur le host");
    		exit(1);
    	}
    	/*
    	Initialiser le adsock avec les infos du host pour préparer adresse d'attachement
    	*/
    	adsock.sin_family=AF_INET;
    	adsock.sin_addr.s_addr=htonl(INADDR_ANY);
    	//récupération du numéro de port
    	adsock.sin_port = htons(Internet_Port);
    	//création du socket
    	if((sd=socket(AF_INET,SOCK_STREAM,0))<0)
    	{
    		perror("Erreur lors de la creation du socket");
    		close(sd);
    		exit(1);
    	}
    	if((bind(sd,&adsock,sizeof(adsock)))<0)
    	{
    		close(sd);
    		perror("Erreur lors du bind");
    		exit(1);
    	}
    	listen(sd,5);
    	//boucle attente connexions
    	for(;;)
    	{
    		lon=sizeof(adsock);
    		if((nsd=accept(sd,&adsock,&lon))<0)
    		{
    			close(nsd);
    			perror("Erreur accept");
    			exit(1);
    		}else{
    			recv(nsd,buf,8,0);
    			printf("Message recu : %s \n",buf);
    			close(nsd);
    		}
    		//envoi de l'acknowledgement
    		if((send(sd,ack,13,0))<0)
    		{
    			perror("Erreur lors de l'ecriture");
    			exit(1);
    		}
    	}
    	close(sd);
    	exit(0);
    }
    Lorsque je lance le client, le message apparaît bien sur le serveur, mais le client plante lors de la tentative de réception de l'acknowledgment :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Erreur accept: Bad file descriptor
    Et le serveur plante totalement lui aussi après réception du message.

    Concernant les codes, le client nous a été donné, et le début du serveur (réception du message et affichage) a été corrigé avec notre professeur.
    Celà fait deux semaines que je cherche à résoudre ce problème, et je ne sais plus quoi faire. Avez-vous une idée ?

    Cdlt,

    Vrashnak

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Le probleme est ici dans le serveur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    		}else{
    			recv(nsd,buf,8,0);
    			printf("Message recu : %s \n",buf);
    			close(nsd);
    		}
    		//envoi de l'acknowledgement
    		if((send(sd,ack,13,0))<0)
    		{
    			perror("Erreur lors de l'ecriture");
    			exit(1);
    		}
    tu recois sur nsd puis tu fermes nsd immédiatement et ensuite, tu envoies l'acquittement sur sd qui est le socket de réception des demandes de connexion (bind + accept)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Ca, c'est dangereux (mais cela marche)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char ack[13]="MESSAGE RECU";
    Ca, c'est mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const char *ack="MESSAGE RECU";
    Même danger dans le client.


    Ca, c'est dangereux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		//envoi de l'acknowledgement
    		if((send(sd,ack,13,0))<0)
    Ca, c'est mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		//envoi de l'acknowledgement
    		if((send(sd,ack,strlen(ack) + 1,0))<0) /* ou strlen(ack) suivant que tu veux envoyer ou pas le 0 terminal de la chaine */
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 19
    Points : 28
    Points
    28
    Par défaut
    Tout d'abord, merci ram-0000 de prendre le temps de me répondre.

    Donc, si j'ai bien compris mon erreur, il faut que je retire le close(nsd) du serveur, et que je crée un nouveau socket pour envoyer l'acknowledgement, c'est bien ça ?

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par Vrashnak Voir le message
    Donc, si j'ai bien compris mon erreur, il faut que je retire le close(nsd) du serveur, et que je crée un nouveau socket pour envoyer l'acknowledgement, c'est bien ça ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    		}else{
    			recv(nsd,buf,8,0);
    			printf("Message recu : %s \n",buf);
    			close(nsd);
    		}
    		//envoi de l'acknowledgement
    		if((send(nsd,ack,13,0))<0)
    		{
    			perror("Erreur lors de l'ecriture");
    			exit(1);
    		}
    
    		// fermeture du socket client
    		close(nsd);
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nsd=accept(sd,&adsock,&lon)
    En faisant ça, sd est donc un socket serveur, dédié à l'écoute. Tu ne peux pas communiquer directement dessus en faisant des send / receive. accept() te renvoie un socket de communication et c'est avec lui que tu dois communiquer, comme dit par Raymond.

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 19
    Points : 28
    Points
    28
    Par défaut
    D'accord ! Merci beaucoup pour votre aide.
    Je tente ça ce soir et vous tiendrai au courant de mon éventuelle réussite. Mais encore merci pour votre aide.

    Édition post-test :

    J'ai fait passer le message par nsd, mais si mon serveur ne plante plus (ce qui en soit est une bonne nouvelle), mon client ne reçoit toujours pas l'acknowledgement., il plante toujours au niveau de l'accept... Or, si j'en crois le man, il faut que je laisse le accept pour que mon client attende le message du serveur. Si je l'enlève, il ne détecte plus l'arrivée du message et s'arrête aussitôt.
    Par contre, ce que je ne comprends pas, c'est pourquoi le write() de mon client passe par sd (donc le socket de bind) mais celui de mon serveur passe par nsd (le socket de communication, si j'ai bien suivi).

    J'ai tellement l'impression d'être à la masse...

  8. #8
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    La fonction accept() est une fonction réservée à la partie serveur ! Elle sert à accepter des connexions entrantes. Sais-tu exactement comment te servir des fonctions des sockets réseau ? Si tu as des doutes, je te te conseille le tutoriel avec lequel j'ai appris le réseau en C et qui m'a resservi il y a un an quand j'ai voulu me rafraîchir les idées : Les sockets en C par Benjamin Roux

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 19
    Points : 28
    Points
    28
    Par défaut
    Je dois reconnaître qu'étant étudiant et surtout débutant en programmation réseau, je ne le savais pas. Merci bktero, encore une erreur que je ne ferai plus.
    En retirant le accept, je reçois bien un message, mais celui-ci a visiblement du mal avec l'encodage et ne fait que 4 ou 5 caractères. Je suppose que le problème vient de mon message à envoyer, car j'ai eu le même avec l'envoi du message simple.
    Je vous remercie tous pour votre aide et d'avoir pris le temps de résoudre mon problème.

  10. #10
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    J'étais étudiant aussi quand j'ai appris à faire des sockets en C, j'ai bien galéré ^^ En pratiquant ça rentrera. De rien et bon courage pour la suite.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème communication serveur/client avec Socket
    Par Nicolas74 dans le forum Entrée/Sortie
    Réponses: 0
    Dernier message: 03/12/2009, 16h54
  2. bug communication Serveur/Client - Indy10 (avec D2009) !
    Par djiga4me dans le forum Web & réseau
    Réponses: 2
    Dernier message: 21/11/2009, 00h46
  3. Communication Serveur Client
    Par ElBarto38 dans le forum Windows Communication Foundation
    Réponses: 14
    Dernier message: 05/03/2009, 11h57
  4. Web Services - Problème de communication serveur/client
    Par vern's dans le forum Web & réseau
    Réponses: 9
    Dernier message: 27/08/2007, 10h06
  5. [servlet][http] communication serveur/client
    Par amel666 dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 03/02/2006, 07h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo