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 :

Architecture C/S : Serveur bloque sur un send() de structure


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 30
    Par défaut Architecture C/S : Serveur bloque sur un send() de structure
    Bonsoir à tous,

    Je dois effectuer une application client/serveur de DL/UL de fichiers.
    Je suis malheureusement bloqué par une erreur que je ne comprends pas. J'ai essayé plein de choses, mais j'arrive à un point de non retour ^^.

    Voici mon 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
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
     
     
    #include <stdlib.h>
    #include <stdio.h>
    #include <linux/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <string.h>
    #include <errno.h> 
    #include "afps.h"
     
    typedef struct sockaddr_in sockaddr_in;
    typedef struct sockaddr sockaddr;
    typedef struct aspartrame aspartrame;
     
    int initbuf(char* buf){
    	char* tmp = buf;
    	for(tmp; tmp < buf + strlen(buf); tmp++){
    		*tmp = 0;
    	}
    	return EXIT_SUCCESS; 
    }
     
    //Fonction de construction de l'aspartrame
    void make_aspartrame(aspartrame* asp, char* action, char* data, char remains){
    	strcpy(asp->action, action);
    	asp->remains = remains;
    	strcpy(asp->data, data);
    	asp->data_size = strlen(asp->data);
    }
     
    int main(int argc,char** argv){
     
    	aspartrame asp = {0};
     
    	FILE* log;
    	log = fopen("serv.log", "w+");
     
    	int sd;		/* Socket Descriptor */
    	int arg_port = 0;
    	int domain, type, protocol;
    	domain = type = protocol = 0;
        char cmd[5] = {0};
        char arg[101] = {0};
        char path[256] = {0};
        char data_buf[8000000] = {0};
        FILE* file;
     
    	/* creation du socket */
    	printf("creation socket\n");
    	sd = socket(AF_INET, SOCK_STREAM, 0);
    	if(sd == INVALID_SOCKET){
        	perror("socket()");
       	 	exit(errno);
    	}
     
    	/* creation de l'interface */
    	printf("creation interface\n");
    	sockaddr_in sin = { 0 }; //structure d'adresse locale
    	sin.sin_addr.s_addr = htonl(INADDR_ANY); //On se met en écoute de toutes les adresses
    	sin.sin_family = AF_INET;
     
    	sin.sin_port = htons(PORT);
     
    	//Affichage de l'en tête serveur de debug
    	printf(" ------- Lancement du serveur de fichier(s) \n");
    	printf(" ------- Port d'ecoute : %d\n", arg_port);
     
    	if( bind(sd, (sockaddr *) &sin, sizeof(sin) ) == SOCKET_ERROR)
    	{
    	    perror("bind()");
    	    exit(errno);
    	}
     
    	/* Configuration de la file d'attente et démarrage de l'écoute */
    	printf("demarrage ecoute\n");
    	if(listen(sd, SIMULTANEOUS_CONNECTIONS) == SOCKET_ERROR)
    	{
    		perror("listen()");
    		exit(errno);
    	}
     
    	sockaddr_in csin = { 0 };
    	int csd = 0; // Client Socket Descriptor
    	int sinsize = 0;
    	char buf[256] = { 0 };
    	char motcode[32] = { 0 };
     
    	while(1){
    		sinsize = sizeof csin;
     
    		//Autorisation de connexion et création d'un nouveau socket pour la communication
    		csd = accept(sd, (sockaddr *)&csin, &sinsize);
    		printf("CSD = %d\n",csd);
    		printf("SD = %d\n", sd);
     
    		make_aspartrame(&asp, "msg", "hello!", 0);
    		printf("coucou\n");
    		printf("pointeur asp = %p\n", &asp);
    		printf("Asp.action = %s\n",asp.action);
    		printf("Asp.data = %s\n",asp.data);
    		send(csd,"pouet",sizeof(asp), 0);
     
    		//send(csd,&asp,sizeof(asp), 0);
    		//send(csd,"A4PH9",6, 0);
    		/* envoi message de bienvenue */
    		initbuf(buf);
    		//printf("Strlen(buf) = %d",strlen(buf));
    		recv(csd,&asp,sizeof(asp),0);
    		//printf("Strlen(buf) = %d",strlen(buf));
    		//printf("Buf = %s\n",buf);
     
     
    		if(strcmp(asp.data, "ready?")){ //Si la data ne contient pas "ready?"
    			printf("Client n'utilisant pas le protocole :%s.\n", asp.data);
    			close(csd);
    		}else{
    			printf("Client utilisant le protocole :%s.\n", asp.data);
    			make_aspartrame(&asp, "msg", "ready!", 0);
    			printf("coucou\n");
    			printf("pointeur asp = %p\n", &asp);
    			printf("Asp.action = %s\n",asp.action);
    			printf("Asp.data = %s\n",asp.data);
    			send(csd,&asp,sizeof(aspartrame), 0);
    			printf("Confirmation de connexion envoyée : %s\n", asp.data);
    //			fopen("schtroumpf", "w+");
     
    			// ecoute permanente
    			while(csd != INVALID_SOCKET){
    				if( csd < 0 ){
    					perror("accept()");
    					exit(errno);
    				}
     
    				/* Attente du paquet client */
    				//initbuf(buf);
    		  		//int lon;
    		  		//if ((lon = read(csd, buf, sizeof(buf))) <=0) return;
    		  		recv(csd, &asp, sizeof(asp), 0);
    		  		//buf[lon-1] = '\0';
    		  		//printf("Message reçu\n");
     
    		  		/* Interprétation du contenu */
    		        //sscanf(buf, "%s %[^\n]", cmd, arg);
    		        printf("\nValeurs saisies");
    		        printf("Cmd=%s.\n",asp.action);
    		        printf("Data=%s.\n",asp.data);
     
    		  		if(!strcmp(asp.action, "stop")){
    		  			printf("fermeture csd\n");
    		  			close(csd);
    		            csd = 0;
    		        //Cas du téléchargement de fichier
    		        }else if(!strcmp(asp.action, "dl")){
    		        	printf("vous souhaitez télécharger le fichier %s.\n", asp.data);
     
    		        	strcpy(path, DEFAULT_PATH);
    		        	strcat(path, asp.data);
    		        	file = fopen(path, "rb");
    		        	if( file == NULL){
    		        		printf("Le fichier %s n'existe pas\n", path);
    		        	}else{
    		        		printf("Le fichier %s existe bien\n", path);
    		        		fread(data_buf, DATA_MAX_SIZE, 1, file);
    		        		make_aspartrame(&asp, "dlr", data_buf, 0);
    		        		send(csd,&asp,sizeof(asp), 0);
    		        	}
     
    		  		}else if(!strcmp(asp.action, "ul")){
    		        	printf("vous souhaitez télécharger le fichier %s", asp.data);
     
    		  		}else{
    		  			printf("Ce n'est pas une commande correcte !\n");
    		  		}
    		  		if(!strcmp(asp.action, "client")){
    		  			printf("SERVEUR !\n");
    		  		}
    		  		//initbuf(cmd);
    		  		//initbuf(arg);
    			}
    		}
    	}
     
    	/* fermeture du socket */
    	close(sd);
    	fclose(log);
    	return EXIT_SUCCESS; 
    }
    Mon serveur bloque au moindre envoi de structure "aspartrame". J'ai essayé avec un simple envoi de char* et ça fonctionne dans ce cas.

    Voici le 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
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
     
     
    #include <stdlib.h>
    #include <stdio.h>
    #include <linux/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <string.h>
    #include <errno.h> 
    #include "afps.h"
     
    typedef struct sockaddr_in sockaddr_in;
    typedef struct sockaddr sockaddr;
    typedef struct in_addr in_addr;
    typedef struct aspartrame aspartrame;
     
    int initbuf(char* buf){
    	char* tmp = buf;
    	for(tmp; tmp < buf + strlen(buf); tmp++){
    		*tmp = 0;
    	}
    	return EXIT_SUCCESS; 
    }
     
    //Fonction de construction de l'aspartrame
    void make_aspartrame(aspartrame* asp, char* action, char* data, char remains){
    	strcpy(asp->action, action);
    	asp->remains = remains;
    	strcpy(asp->data, data);
    	asp->data_size = strlen(asp->data);
    }
     
    int main(int argc,char** argv){
    	FILE* log;
    	log = fopen("cli.log", "w+");
    	aspartrame asp = {0};
    	char* prog;
    	char* host;
    	/* char* fichier;
    	char* nom_fichier; */
     
    	/* test des arguments */
    	if (argc<2||argc>3){
    		/* pas d'argument */
    		perror("Erreur arguments\narguments : host (adresse ip)\n");
    		exit(1);
    	}
     
    	/* recuperation des arguments */
    	printf("Recuperation des arguments :\n");
    	prog = argv[0];
    	host = argv[1];
    	//fichier = argv[2];
    	//if(argv[3]==NULL) nom_fichier = argv[2];
    	//else nom_fichier= argv[3];
    	printf("prog : %s\n",prog);
    	printf("host : %s\n",host);
    	//printf("fichier : %s\n",fichier);
    	//printf("nom fichier : %s\n",nom_fichier);
     
    	/* -----------------------------------------*/
     
    	/* creation du socket */
    	int sd = 0;
    	sd = socket(AF_INET, SOCK_STREAM, 0);
    	if(sd == INVALID_SOCKET){
        	perror("socket()");
       	 	exit(errno);
    	}
     
    	/* connexion au serveur */
    	struct hostent *hostinfo = NULL;
    	sockaddr_in sin = { 0 }; /* initialise la structure avec des 0 */
     
    	hostinfo = gethostbyname(host); /* on récupère les informations de l'hôte auquel on veut se connecter */
    	if (hostinfo == NULL) /* l'hôte n'existe pas */
    	{
    		printf ("Unknown host %s.\n", host);
    		exit(EXIT_FAILURE);
    	}
     
    	sin.sin_addr = *(in_addr *) hostinfo->h_addr; /* l'adresse se trouve dans le champ h_addr de la structure hostinfo */
    	sin.sin_port = htons(PORT); /* on utilise htons pour le port */
    	sin.sin_family = AF_INET;
     
    	if(connect(sd,(sockaddr *) &sin, sizeof(sockaddr)) == SOCKET_ERROR)
    	{
    		perror("connect()");
    		exit(errno);
    	}
    	// la connexion est établie
     
    	/* envoi */
     
    	char buffer[1024];
     
    	recv(sd, &asp, sizeof(asp), 0);
     
    	if(strcmp(asp.data, "hello!")) return;
     
    	make_aspartrame(&asp, "msg", "ready?", 0); 
     
    	if(send(sd, &asp, sizeof(asp), 0) < 0)
    	{
    		perror("send()");
    		exit(errno);
    	}
     
    	printf("Demande de connexion envoyee\n");
    	printf("\n");
     
    	recv(sd, &asp, sizeof(asp), 0);
    	printf("DATA = %s", asp.data);
     
    	/*while(&sd != NULL){
    		printf("Tchou tchou\n");
    		close(sd);
    	}*/
    	fclose(log);
    }
    Mon client n'a pas de problèmes pour envoyer la structure au serveur qui peut les lire.

    Tout ça me semble très louche, car c'est un contexte particulier qui n'est pas possible (envoi d'une structure trame, du serveur au client).

    Cela m'ennuie de devoir passer par des buffers simples pour passer l'information car je sais que la communication par structure est possible.

    Please help !

    Merci de m'avoir lu.

  2. #2
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Règles en communication binaire (notamment par structure) :
    • S'assurer de l'endianness.
    • S'assurer de l'alignement.
    • Vérifier les tailles des données / structures / types de base.


    Dans ton cas, je te conseille déjà de commencer par afficher le sizeof de la structure sur les deux cibles, et de t'assurer qu'elles sont bien identiques.

    De plus, tu devrais utiliser memcpy au lieu de strcpy pour des données binaires, sinon tu t'exposes à des ennuis sévères.

    Par contre, il faudrait aussi la définition de struct aspartrame pour vérifier si tu n'a pas mis des valeurs incorrectes pour la taille dans les send / recv.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 30
    Par défaut
    Merci beaucoup de cette réponse.

    Je mets le contenu de afps.h :

    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
     
     
    /* 	--- AFP ---
     
    	Aspartrame AFP :
     
    	Commandes :
    	- help			// affiche l'aide
    	- list                 // retourne la liste des fichiers
    	- dl [filename] // download
    	- up [filename] // upload
    	- stop// quitter le serveur et fermer le socket
     
    */
     
    #define ACTION_SIZE 4
    #define DATA_MAX_SIZE 1000000
    #define PORT 1940
    #define DEFAULT_PATH "Serveur/"
    #define SIMULTANEOUS_CONNECTIONS 5
    #define INVALID_SOCKET -1
    #define SOCKET_ERROR -1
     
    // Messages du serveur
    #define AFPS100 "Hello_ok\n"	// Serveur prêt pour communication
     
    // Messages du client
     
    // Erreur du serveur
     
    // Erreur du client
     
    /* Structure Aspartramme */
    struct aspartrame{
    	char action[ACTION_SIZE + 1];
    	char remains;
    	unsigned int data_size;
    	char data[DATA_MAX_SIZE + 1];
    };
     
    typedef struct sockaddr_in sockaddr_in;
    typedef struct sockaddr sockaddr;
    typedef struct in_addr in_addr;
    typedef struct aspartrame aspartrame;
    Je pense que l'endianness ne pose pas de problème car le serveur reçoit correctement les aspartrames que lui envoie le client. Est-il possible que l'on envoie en Little Endian d'un côté, et en Big Endian de l'autre ??

  4. #4
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par WhiteD Voir le message
    Est-il possible que l'on envoie en Little Endian d'un côté, et en Big Endian de l'autre ??
    L'endianness dépend du processeur : si ce sont deux x86 de chaque côté, non, ce n'est pas possible.

    Ta structure de trame semble correcte : tu as vérifié la valeur du sizeof de chaque côté ?
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

Discussions similaires

  1. Réponses: 9
    Dernier message: 08/06/2015, 16h48
  2. Serveur socket multi client qui bloque sur le premier client
    Par cyclopsnet dans le forum Entrée/Sortie
    Réponses: 1
    Dernier message: 07/05/2014, 21h31
  3. Javascript bloqué sur serveur dédié
    Par toufik135 dans le forum Général JavaScript
    Réponses: 27
    Dernier message: 07/02/2014, 17h10
  4. Port 8181 bloqué sur serveur Debian?
    Par josse34 dans le forum Debian
    Réponses: 9
    Dernier message: 25/10/2012, 16h46
  5. base de donnees sur serveur application sur client
    Par rabi dans le forum Bases de données
    Réponses: 4
    Dernier message: 12/05/2004, 21h04

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