Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 06/01/2007, à 13:40

Sebome

Client / Serveur c/c++

Bonjours à tous,
J'essaye de faire un petit client/serveur pour échanger des fichiers sur mon réseau local (pour comprendre le principe).Le client se connecte au serveur et le serveur lui envoi un fichier.
Le problème est que le fichier reçu par le client n'est pas bon , il n'est pas identique au fichier envoyé par le serveur et je ne comprend pas trop pourquoi...:(

Voici le code :
Client :

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;

#define TAILLE_BUF 1000


int main ()
{
	/*** Declaration des fonction ***/
	void Traitement(int sockfd);

	/*** Declaration des variables ***/
	int sockfd, n;
	int port;
	struct sockaddr_in servaddr;
	char ad_serveur[255];

	/*** Code ***/

	//saisie de la configuration

	cout<< "Entrer l'adresse IP du serveur : ";

	cin >> ad_serveur;

	cout << endl << "Entrer le port du serveur : ";

	cin >> port;


  
	if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{    
		//la fonction socket cree un socket de flux (SOCK_STREAM)internet(AF_INET)
		//(incomprehensible en francais)(plus simplement : Internet stream socket).
		//Renvoit un int pour identifier le socket plus tard (cf. read & connect)
		perror("socket error");        
		exit(1);
	}
    
	bzero(&servaddr, sizeof(servaddr));    
	//on met toute la structure a 0
	//on remplit la structure avec l'ip du serveur et le num de son port
   
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(port);
	//htons: pour convertir le numero de port

 	if (inet_pton(AF_INET, ad_serveur, &servaddr.sin_addr) <= 0)
	{
		//inet_pton: convertit l'argument ASCII (Ex: 127.0.0.1) dans le bon format
		perror("inet_pton error");
		exit(1);
	}

	if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
	{
		//connect etablit la connection TCP avec le serveur specifie par la structure de
		//l'adresse du socket pointe par le second argument
		perror("connect error");                        
 		exit(1);

	}

	Traitement(sockfd);

	return 0;
}



void Traitement(int sockfd)
{
	/*** Declaration des variables ***/


	int taille,temp,lg,erreur;

	char nom_fichier[50];

	char transfert[TAILLE_BUF+1];

	char indirection[100];

	char ok[]={'o','k','\0'};

	FILE* fichier;




	/*** Code ***/


	cout << endl << "Connecter au serveur!" << endl;

	cout << endl << endl << "Entrer l'indirection ou vous voulez enregistrer le fichier (ex : '/media/hda2/') : ";

	cin >> indirection;


	erreur = write(sockfd,ok,sizeof(ok));


	if (erreur < 0)

	{

		perror("Erreur write");
		exit(1);

	}


	cout << endl << "Reception du nom de fichier..." << endl;


	erreur = read(sockfd,(char*)&nom_fichier,sizeof(nom_fichier));


	if (erreur < 0)

	{

		perror("Erreur read");
		exit(1);

	}


	cout << endl << "Nom du fichier : " << nom_fichier << endl;

	cout << endl << "Reception de la taille du fichier..." << endl;


	erreur = read (sockfd,(char*)&taille,sizeof(taille));


	if (erreur < 0)

	{

		perror("Erreur read");
		exit(1);

	}


	cout << endl << "Taille du fichier : " << taille << " octets" << endl;

	

	strcat(indirection,nom_fichier);



	fichier=fopen(indirection,"w+b");

	if(fichier == NULL)

	{

		perror("Erreur d'ouverture fichier");
		exit(1);

	}



	temp=taille;



	cout << endl << "Reception en cours..." << endl;


	while(temp>TAILLE_BUF)	//si la taille du fichier est supérieure à la taille du buffer

	{

		lg = read(sockfd, transfert, TAILLE_BUF);
		//transfert[lg]=0;


		if (lg < 0)

		{

			perror("Erreur read");
			exit(1);

		}

		fwrite(transfert,1,lg,fichier);

		temp=temp-TAILLE_BUF;						

	}


	lg = read(sockfd, transfert, TAILLE_BUF);
	transfert[lg]=0;


	if (lg < 0)

	{

		perror("Erreur read");
		exit(1);

	}

	fwrite(transfert,1,lg,fichier);




	cout << endl << "Reception terminee" << endl;

	cout << endl << "Fichier enregistre : " << indirection << endl;


	



	fclose(fichier);


}

Serveur :

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <string.h>
#include <stdio.h>
using namespace std;

#define TAILLE_BUF 1000
 
int main()
{

	/*** Declaration des fonction ***/
	void Traitement(int connfd);

	/*** Declaration des variables ***/
	int port;
	int listenfd;
	int connfd;
	struct sockaddr_in    servaddr;

	/*** Code ***/
	cout << "Entrer le port du serveur : ";
	cin >> port;

	if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
	{
		perror("socket error");                        
         	exit(1);
	}
	bzero(&servaddr, sizeof(servaddr));//on met toute la structure a 0    

	//on remplit la structure avec l'ip du serveur et le num de son port
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY signifie que le serveur va accepter une connection client sur n'importe-quelle interface
	servaddr.sin_port = htons(port);

	//on lie le port du serveur au socket en remplissant la "internet socket
	//adresse structure" et en appellant bind
	if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
	{    
		perror("bind error");                        
		exit(1);
 	
	}

	//avec listen, le socket est converti en listening socket (ecoute)
	//sur lequel les demandes de connections vont etre acceptees par le Kernel 
	if (listen(listenfd, 1) < 0)
	{
		perror("listen error");
		exit(1);
	}

	//accept retourne un "descripteur de connection" (connected descriptor) qui est
	//utilise pour la communication avec le nouveau client. Un nouveau pour chaque client
	if ((connfd = accept(listenfd, (struct sockaddr *) NULL, NULL)) < 0)
	{
		perror("accept error");
		exit(1);
	}
	Traitement(connfd);
	close(connfd);
	return 0;
}




void Traitement (int connfd)
{
	/*** Declaration des variables ***/

	char indirection[100];

	char nom_fichier[50];

	char ok[3];

	char transfert[TAILLE_BUF+1];

	FILE* fichier;

	int taille,temp=0,i,j,lg,lg_nom,lg_chaine,erreur;


	/*** Code ***/

	erreur=read(connfd,(char*)ok,sizeof(ok));

	if (erreur < 0)
	{
		perror("Erreur read");
		exit(1);
	}

	if (strcmp(ok,"ok")!=0)

	{

		cout << endl << "ERREUR" << endl;

		exit(1);

	}

	cout << endl << "Client ok !" << endl;

	//demande indirection fichier à envoyer

	cout<<endl<<endl<<"Entrer l'indirection complette du fichier a envoyer (ex : /media/hda2/metro.pdf)" << endl << "il ne doit pas y avoir d'espace dans le l'indirection : ";

	cin>>indirection;

	//on ouvre le fichier et on test si il existe
	fichier=fopen(indirection,"r+b");

	if(fichier == NULL)

	{

		perror("Erreur d'ouverture du fichier");

		exit(1);

	}

	//On recupere le nom du fichier dans l'indirection

	lg_chaine=strlen(indirection);

	i=lg_chaine -1;

	lg_nom=0;

	while((indirection[i])!='/')

	{

		lg_nom++;

		i--;

	}

	j=0;

	for (i=(lg_chaine - lg_nom); i<= lg_chaine; i++)

	{

		nom_fichier[j]=indirection[i];

		j++;

	}

	//on envoi le nom du fichier
	cout << endl << "Envoie du nom du fichier" << endl;

	erreur = write(connfd,(char*)&nom_fichier,sizeof(nom_fichier));
	if (erreur < 0)
	{
		perror("Erreur write");
		exit(1);
	}


	fseek( fichier, 0, SEEK_END );	//on se place a la fin du fichier

    	taille=ftell(fichier);		//on récupere la position donc la taille

	fseek( fichier, 0, SEEK_SET );	//on se replace au début du fichier

     

	cout << endl << "taille du fichier: "<<taille<<" octets"<<endl;

	cout << endl << "Envoie de la taille du fichier: "<<endl;


	//on envoi la taille du fichier
	erreur = write(connfd,(char*)&taille,sizeof(taille));
	if (erreur < 0)
	{
		perror("Erreur write");
		exit(1);
	}

	temp = taille;


	cout << endl << "Transfert en cours ..." << endl;

	while (temp > TAILLE_BUF)
	{
		lg = fread(transfert,1, TAILLE_BUF, fichier);
		//transfert[lg]=0;
		if (lg <= 0)
		{
			perror("Erreur fread");
			exit(1);
		}
		erreur = write(connfd,transfert,lg);
		if (erreur < 0)
		{
			perror("Erreur write");
			exit(1);
		}
		temp = temp - TAILLE_BUF;
	}

	lg=fread(transfert,1, TAILLE_BUF, fichier);
	//transfert[lg]=0;
	if (lg <= 0)
	{
		perror("Erreur fread");
		exit(1);
	}
	erreur = write(connfd,transfert,lg);
	if (erreur < 0)
	{
		perror("Erreur write final");
		exit(1);
	}


	fclose (fichier);

	cout << endl << "FICHIER TRANSMIS !!!" << endl;

}

si quelqu'un voit où est le problème...

Merci d'avance!

Hors ligne

#2 Le 06/01/2007, à 20:45

Sebome

Re : Client / Serveur c/c++

Cela ne vous inspire pas? sad
Mon code est peu être trop nul hmm

Hors ligne

#3 Le 07/01/2007, à 01:16

naekun

Re : Client / Serveur c/c++

Euh ... bon il manque des tests pour les saisies, j'ai galéré un ptit peu, manque de / final pour les repetoires par exemple ... et en cas de crash du a un probleme de saisie le port reste ouvert hmm

mébon, au final ... chez-moi-ça-marche.

J'ai essayé avec un fichier ascii court et le transfert se fait. Le fichier téléchargé est identique au fichier d'origine. Et je viens d'essayer avec un fichier plus long au cas où (un Makefile) et c'est bon aussi.

Donc, euh, je ne vois pas où est ton problême ?

Hors ligne

#4 Le 08/01/2007, à 11:49

Sebome

Re : Client / Serveur c/c++

Un fichier texte par exemple ca passe sans probleme, mes si j'essaye avec autre chose comme une video ou un pdf ca marche plus...

Hors ligne