Problème socket transfert d'image en C

Résolu/Fermé
Gibbs - 21 mars 2011 à 09:05
 Gibbs - 24 mars 2011 à 17:44
Bonjour,
Cela fait près de 3 ou 4 semaines que je travaille sur une socket serveur et une socket client en langage C.
Il s'agit d'une caméra IP qui va prendre, sur un intervalle de temps quelconque des photos d'un tunnel. Je récupère cette image (qui à une taille d'environ 21 Ko) et je souhaite l'envoyer à une socket serveur.
La socket serveur va récupérer cette image pour que, je puisse la visualiser par la suite bien sûr.
Voila ce que je veux dans les granddes lignes.
Je ne sais pas si c'est à l'envoi ou à la réception qu'il y a problème.

Je suis sous Linux.
Voici ma socket client :

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define taille_max 21470 //Définition de la taille du tableau
typedef struct sockaddr_in sockaddr_in;
struct sockaddr * sockaddr;

int main(int argc, char *argv[])
{
//Declaration des variables
int sock_client, connection, i, envoi, reception, cloture, taille;
char reponse[256];
char *p_reponse;
p_reponse=reponse;
FILE *psf=NULL;
char lecture[taille_max];
char *psl;
psl=lecture;

/* contexte d'adressage socket serveur */
sockaddr_in sin;

/* contexte d'adressage socket client */
sockaddr_in csin;

//Creation de la socket serveur
if(sock_client=socket(AF_INET, SOCK_STREAM, 0))
{
printf("La creation de la socket client a reussi !\n");

//Définition du contexte d'adressage client
sin.sin_addr.s_addr = inet_addr("192.168.109.174"); // Adresse IP du serveur
sin.sin_family = AF_INET; // Famille de protocole TCP
sin.sin_port = htons(1081); //Port où ira se connecter la socket client

//Connexion au serveur
if((connection=connect(sock_client, (struct sockaddr*)&sin, sizeof(sin))==0))
{
printf("La connexion au serveur a reussi !\n");

//Ouverture du fichier qui sera envoyé
if((psf=fopen("projet.jpg","rb"))!=NULL)
{
printf("L'ouverture du fichier a reussi !\n");

if(psf!=NULL)
{

while(fgets(psl, sizeof(lecture), psf)!=NULL)
{
//Envoi du contenu au serveur
envoi=send(sock_client, psl, sizeof(psl), 0);
}
//Fermeture du fichier
if(fclose(psf)==0) { printf("La fermeture du fichier a reussi !\n"); }
else { printf("La fermeture du fichier a echoue !\n"); }
}
printf("L envoi du fichier est terminee !\n");

//Réception de la reponse du serveur
if((reception=recv(sock_client, reponse, sizeof(reponse)-1, 0))!=-1)
{
printf("La reponse du serveur a ete recu !\n");
printf("%s",reponse);
} //Fin if reception
else { printf("La reception de la reponse du serveur a echoue !\n"); }
} // Fin if envoi
else { printf("L'ouverture du fichier a echoue !\n"); }
} // Fin du if connexion au serveur
else { printf("La connexion au serveur a echoue !\n"); }
} // Fin du if creation de la socket client
else { printf("La creation de la socket client a echoue !\n"); }

//Fermeture de la socket
if((cloture=close(sock_client))==0)
{
printf("La fermeture de la socket client a reussi !\n");
}
else { printf("La fermeture de la socket client a echoue !\n"); }
return(0);
}



et ma socket serveur :




#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

/* struct sockaddr est une référance générique pour les appels systèmes
donc pas besoin de le déclarer. Il faut donc simplement caster (changer)
votre sockaddr_in en sockaddr.
*/
typedef struct sockaddr_in sockaddr_in;
struct sockaddr *sockaddr;

int main(void)
{
// Declaration des variables
int sock_serveur, resultat_bind, ecoute, accepter, taille_csin, i, recept, envoi, fermeture, taille=0;
char buf[21500];
char *p_buf;
p_buf=buf;
char reponse[256];
FILE *psf;

/* contexte d'adressage socket serveur */
sockaddr_in sin;

/* contexte d'adressage socket client */
sockaddr_in csin;

//Creation de la socket serveur
if(sock_serveur=socket(AF_INET, SOCK_STREAM, 0))
{
printf("La creation de la socket reussi !\n");

//Definition du contexte d'adressage serveur
sin.sin_addr.s_addr=htonl(INADDR_ANY); // Adresse IP du serveur
sin.sin_family=AF_INET; // Famille de protocole TCP
sin.sin_port=htons(1081); //Port utilise par la socket

// Association du contexte d'adressage serveur a la socket serveur creer
if(resultat_bind=bind(sock_serveur, (struct sockaddr*)&sin, sizeof(sin))==0)
{
printf("Le bind a reussi !\n");

// Attente d'une connexion client
if((ecoute=listen(sock_serveur,5))==0)
{
printf("En attente d'une connexion client ...\n");

//Acceptation de la connexion client par le serveur
taille_csin=sizeof(csin);
if((accepter=accept(sock_serveur, (struct sockaddr*)&sin,&taille_csin))!= -1)
{
printf("Connexion client acceptee !\n");

// Creation et/ou ouverture du fichier
if((psf=fopen("projet.jpg","w+"))!=NULL)
{
printf("L'ouverture du fichier a reussi !\n");

//Reception du fichier envoye par le client
if(psf!=NULL)
{
while(recept=recv(accepter, buf, sizeof(buf), 0)!=-1)
{
if(strcmp(buf,"end")!=0) { break; }
fputs(p_buf, psf);
}
printf("Ecriture terminee !\n");
}
//Fermeture du fichier
if((fclose(psf))==0) { printf("La fermeture du fichier a reussi !\n"); }
else { printf("La fermeture du fichier a echoue !\n"); }
printf("Reception et ecriture du fichier terminee !\n");

//Envoi de la reponse au client
if((envoi=send(accepter, "Hello ! Moi, serveur, je vous remercie pour votre message", 57, 0))!= -1)
{
printf("Envoi de la reponse au client reussi !\n");
}
else { printf("L'envoi de la reponse au client a echoue !\n"); }
} // Fin du if creation/ouverture du fichier
else { printf("La creation/ouverture du fichier a echoue !\n"); }
} // Fin du if acceptation connexion client
else { printf("L'acceptation de la connexion du client a echoue !\n"); }
} // Fin du if attente connexion client
else { printf("La mise en ecoute a echoue !\n"); }
} // Fin du if bind
else { printf("Le bind a echoue !\n"); }
} // Fin du if creation socket serveur
else { printf("La creation de la socket serveur a echoue !\n"); }

//Fermeture de la socket serveur
if((fermeture=close(sock_serveur))==0)
{
printf("Fermeture de la socket reussi !\n");
}
else { printf("Probleme lors de la fermeture de la socket serveur"); }
return(0);
}

Si quelqu'un peut m'aider ! Merci d'avance.

A voir également:

3 réponses

Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
Modifié par Char Snipeur le 21/03/2011 à 19:28
int file; 
int taille; 
read(accepter,&taille,sizeof(int)); 
buffer=(char*)malloc(taille*sizeof(int)); 
if((file=open("projet.jpg", O_RDONLY|O_CREAT|O_TRUNC|S_IREAD))!=-1) 
{ 
  printf("L'ouverture du fichier a reussi !\n"); 

//Reception du fichier envoye par le client 
  do { 
    lu=read(accepter, (char *)buffer, taille); 
    printf("Nombre d'octets lus : %d octets\n",lu); 
    if(lu>0) { 
      ecrit=write(file, (char *)buffer, lu); 
      printf("Nombre d'octets ecrits : %d octets\n",ecrit); 
    } 
  } 
  while(lu<taille && ecrit>0); 

printf("Ecriture terminee !\n"); 


Socket Client :
int file; 
int taille; 
if((file=open("projet.jpg",O_RDONLY))!=-1) 
{ 
printf("L'ouverture du fichier a reussi !\n"); 
taille=lseek(fichier,0,SEEK_END); 
lseek(fichier,0,SEEK_SET); 
buffer=(char*)malloc(taille*sizeof(int)); 
write(sock_client,&taille,sizeof(int));

//Lecture et envoi des donnees 
do { 
lu=read(file, (char *)buffer, taille); 
printf("Nombre d'octets lus : %d octets\n",lu); 
if(lu>0) { 
ecrit=write(sock_client, (char *)buffer, lu); 
printf("Nombre d'octets envoyes : %d octets\n",ecrit); 
} 
} 
while(lu!=0 && ecrit>0);

j'ai ajouté l'envoie réception de la taille de l'image ainsi que l'allocation dynamique de buffer.
Et normalement dans ce cas là, il n'y a pas besoin de boucler. ça peut simplifier le problème.il n'y a plus qu'a tester ;)
Essai d'être plus précis lorsque tu dis que ça ne fonctionne pas : l'erreur, les sorties consoles etc.
La vrai soumission c'est quand les esclaves s'inquiètent du cours du coton.
Char Snipeur
1
Bonjour Char Snipeur,
Merci pour ta réponse. J'ai bien travaillé sur ce que tu m'a dit et surtout sur mes boucles et j'ai finalement trouvé la solution. Ca fonctionne.
Merci encore.
1
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
24 mars 2011 à 15:50
tant mieux.
Si tu pouvais expliquer ta solution, ça serait bien.
Merci.

(J'ai mi le sujet en résolu)
0
Pour le client j'ai fais de cette façon :

//Ouverture du fichier qui sera envoyé
if((file=open("iphone4.jpg",O_RDONLY))!=-1)
{
printf("L'ouverture du fichier a reussi !\n");

//Envoi de la taille du fichier
taille=lseek(file, 0, SEEK_END);
lseek(file, 0, SEEK_SET);
printf("\nTaille du fichier : %d octets.\n\n", taille);
write(sock_client, &taille, sizeof(taille));

//Lecture et envoi des donnees
while(fin<taille)
{
if((lu=read(file, &buffer, sizeof(buffer)))!=-1)
{
printf("Nombre d'octets lus : %d octets\n", lu);
} else break;

if((envoi=write(sock_client, &buffer, lu))!=-1)
{
printf("Nombre d'octets envoyes : %d octets\n", envoi);
} else break;

te+=envoi;
fin+=lu;
}

printf("\nNombre d'octets total envoyes : %d octets\n\n", te);

Après je ferme bien entendu le fichier.

Pour le serveur :

if((file=open("image_recu.jpg", O_WRONLY|O_CREAT|O_TRUNC|S_IREAD))!=-1)
{
printf("L'ouverture du fichier a reussi !\n");

//Réception de la taille du fichier
read(accepter, &tf, sizeof(tf));
printf("\nTaille du fichier : %d octets\n\n", tf);

//Reception du fichier envoye par le client et ecriture du fichier
while(fin<tf)
{
if ((lu=read(accepter, &buffer, sizeof(buffer)))!=-1)
{
printf("Nombre d'octets lus : %d octets\n", lu);
} else break;

if((ecrit=write(file, &buffer, lu))!=-1)
{
printf("Nombre d'octets ecrits : %d octets\n", ecrit);
} else break;

te+=ecrit;
fin+=lu;
}

printf("\nNombre d'octets total ecrits : %d octets\n\n", te);
printf("Ecriture terminee !\n");

Je referme encore le fichier. Voila !!
L'un des gros problèmes que j'avais, et le plus bête d'ailleurs, c'est que côté serveur à la réception, au lieu de créer le fichier en écriture seule, afin de pouvoir écrire les données reçues, je l'avais créer en lecture seule !!, c'est pourquoi la fonction "write" me renvoyait toujours "-1". J'ai modifier les boucles aussi et voilà le travail !!
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
21 mars 2011 à 12:08
Salut.
J'ai lu rapidement le code, je n'ai rien vu de débile.
Je trouve que dans l'ensemble c'est bien écrit, du coup tu devrais rapidement trouver l'erreur.
D'ailleur un peu de précision serait bien venu. Comme tu fais plein de sorties, à quelle niveau ça merde ? Explique mieux ce qui ne fonctionne pas.
Quelques petites remarques :
sur le serveur ouvre ton fichier en "w" et non "w+", c'est plus logique, il n'y a pas de raison que tu conserves ce qu'il y avait avant.
dans tes boucles d'envoi et de réception, fait une sortie du nombre d'octet envoyé et reçus, pour être certain de la concordance entre les deux.
Bonne chance.
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
21 mars 2011 à 12:16
if(psf!=NULL)
{
while(recept=recv(accepter, buf, sizeof(buf), 0)!=-1)
{
if(strcmp(buf,"end")!=0) { break; }
fputs(p_buf, psf);
} 

je vois deux problèmes potentiel : tu attends un "end" que tu n'envoie pas et pour moi recv est bloquant, il ne sait pas que le client a fini, je mettre plutôt un truc du genre while(recept=...<sizeof(buf))
autre remarque, la variable p_buf ne sert à rien et rend plus difficile la lecture du source.
Maintenant que j'y songe, fputs et fgets sont assez mal choisi car opèrent en ligne. Mieux vaut utiliser les fonctions de lecture binaires pour les fichiers images (read write). Car sinon tu peux avoir des erreurs avec les octets nuls ou de retour à la ligne.
0
Salut.
Merci pour ta réponse. En faitn lorsque j'envoie le fichier, à la réception il doit y avoir un souci au niveau de la boucle d'écriture je pense puisque au lien d'avoir 21 Ko, il m'arrive d'avoir 120 Mo. C'est fou
0
J'ai travaille dessus entre temps. Je vais remettre ce que j'ai fais
0
Serveur :

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

/* struct sockaddr est une référance générique pour les appels systèmes
donc pas besoin de le déclarer. Il faut donc simplement caster (changer)
votre sockaddr_in en sockaddr.
*/
typedef struct sockaddr_in sockaddr_in;
struct sockaddr *sockaddr;

int main(void)
{
// Declaration des variables
int sock_serveur, resultat_bind, ecoute, accepter, taille_csin, i, recept=0, envoi, fermeture, taille=0;
char buf[21470];
char *p_buf;
p_buf=buf;
char reponse[256];
FILE *psf;

/* contexte d'adressage socket serveur */
sockaddr_in sin;

/* contexte d'adressage socket client */
sockaddr_in csin;

//Creation de la socket serveur
if(sock_serveur=socket(AF_INET, SOCK_STREAM, 0))
{
printf("La creation de la socket reussi !\n");

//Definition du contexte d'adressage serveur
sin.sin_addr.s_addr=htonl(INADDR_ANY); // Adresse IP du serveur
sin.sin_family=AF_INET; // Famille de protocole TCP
sin.sin_port=htons(1081); //Port utilise par la socket

// Association du contexte d'adressage serveur a la socket serveur creer
if(resultat_bind=bind(sock_serveur, (struct sockaddr*)&sin, sizeof(sin))==0)
{
printf("Le bind a reussi !\n");

// Attente d'une connexion client
if((ecoute=listen(sock_serveur,5))==0)
{
printf("En attente d'une connexion client ...\n");

//Acceptation de la connexion client par le serveur
taille_csin=sizeof(csin);
if((accepter=accept(sock_serveur, (struct sockaddr*)&sin,&taille_csin))!= -1)
{
printf("Connexion client acceptee !\n");

// Creation et/ou ouverture du fichier
if((psf=fopen("projet.jpg","w+"))!=NULL)
{
printf("L'ouverture du fichier a reussi !\n");

//Reception du fichier envoye par le client
do {
recept+=recv(accepter, buf, sizeof(buf), 0);
}
while(recept<=21470);
printf("Reception terminee\n");
printf("Taille de buf= %d\n",sizeof(buf));


//Ecriture des donnees recus dans un fichier
do {
fputs(p_buf, psf);
}
while(p_buf!=NULL);
printf("Ecriture terminee !\n");
//Fermeture du fichier
if((fclose(psf))==0) { printf("La fermeture du fichier a reussi !\n"); }
else { printf("La fermeture du fichier a echoue !\n"); }
printf("Reception et ecriture du fichier terminee !\n");

//Envoi de la reponse au client
if((envoi=send(accepter, "Hello ! Moi, serveur, je vous remercie pour votre message", 57, 0))!= -1)
{
printf("Envoi de la reponse au client reussi !\n");
}
else { printf("L'envoi de la reponse au client a echoue !\n"); }
} // Fin du if creation/ouverture du fichier
else { printf("La creation/ouverture du fichier a echoue !\n"); }
} // Fin du if acceptation connexion client
else { printf("L'acceptation de la connexion du client a echoue !\n"); }
} // Fin du if attente connexion client
else { printf("La mise en ecoute a echoue !\n"); }
} // Fin du if bind
else { printf("Le bind a echoue !\n"); }
} // Fin du if creation socket serveur
else { printf("La creation de la socket serveur a echoue !\n"); }

//Fermeture de la socket serveur
if((fermeture=close(sock_serveur))==0)
{
printf("Fermeture de la socket reussi !\n");
}
else { printf("Probleme lors de la fermeture de la socket serveur"); }
return(0);
}


Client :

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define taille_max 1024 //Définition de la taille du tableau
typedef struct sockaddr_in sockaddr_in;
struct sockaddr * sockaddr;

int main(int argc, char *argv[])
{
//Declaration des variables
int sock_client, connection, i, envoi=0, reception, cloture;
char fichier[21470];
char *psfich=fichier;
char reponse[256];
char *p_reponse;
p_reponse=reponse;
FILE *psf=NULL;
/* char lecture[taille_max];
char *psl;
psl=lecture;*/

/* contexte d'adressage socket serveur */
sockaddr_in sin;

/* contexte d'adressage socket client */
sockaddr_in csin;

//Creation de la socket serveur
if(sock_client=socket(AF_INET, SOCK_STREAM, 0))
{
printf("La creation de la socket client a reussi !\n");

//Définition du contexte d'adressage client
sin.sin_addr.s_addr = inet_addr("192.168.109.174"); // Adresse IP du serveur
sin.sin_family = AF_INET; // Famille de protocole TCP
sin.sin_port = htons(1081); //Port où ira se connecter la socket client

//Connexion au serveur
if((connection=connect(sock_client, (struct sockaddr*)&sin, sizeof(sin))==0))
{
printf("La connexion au serveur a reussi !\n");

//Ouverture du fichier qui sera envoyé
if((psf=fopen("projet.jpg","r"))!=NULL)
{
printf("L'ouverture du fichier a reussi !\n");

//Stockage des donnees dans un tableau de char
do {

}
while(fgets(psfich, sizeof(fichier), psf)!=NULL);

//Envoi des donnees
for(i=1; i<=21470; i++)
{
envoi+=send(sock_client, psfich, 1, 0);
printf("send= %d\n", envoi);
}

//Fermeture du fichier
if(fclose(psf)==0) { printf("La fermeture du fichier a reussi !\n"); }
else { printf("La fermeture du fichier a echoue !\n"); }
printf("L envoi du fichier est terminee !\n");

//Réception de la reponse du serveur
if((reception=recv(sock_client, reponse, sizeof(reponse)-1, 0))!=-1)
{
printf("La reponse du serveur a ete recu !\n");
printf("%s\n",reponse);
} //Fin if reception
else { printf("La reception de la reponse du serveur a echoue !\n"); }
} // Fin if envoi
else { printf("L'ouverture du fichier a echoue !\n"); }
} // Fin du if connexion au serveur
else { printf("La connexion au serveur a echoue !\n"); }
} // Fin du if creation de la socket client
else { printf("La creation de la socket client a echoue !\n"); }

//Fermeture de la socket
if((cloture=close(sock_client))==0)
{
printf("La fermeture de la socket client a reussi !\n");
}
else { printf("La fermeture de la socket client a echoue !\n"); }
return(0);
}
0
J'ai vu que lorsqu'on ouvre un fichier en w+, le contenu déjà présent sera écrasé afin de pouvoir écrire dessus
0