Pages : 1
#1 Le 06/01/2007, à 12: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, à 19:45
- Sebome
Re : Client / Serveur c/c++
Cela ne vous inspire pas?
Mon code est peu être trop nul
Hors ligne
#3 Le 07/01/2007, à 00: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
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, à 10: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
Pages : 1