Protocole de transfert de fichiers en TCP/IP

Voir le sujet précédent Voir le sujet suivant Aller en bas

Protocole de transfert de fichiers en TCP/IP

Message  Mr_belette le Dim 6 Déc 2009 - 1:39

Bonjour à tous,

Je rencontre un problème de fonctionnement dans une application de transfert de fichiers par TCP/IP. Ici, seulement l'aspect théorique des choses m'intéresse:
La façon de procéder dans cette application est la suivante:

1 - Le serveur se lance et écoute
2 - Le client se connecte au serveur
3 - Lors de la connexion, le serveur envoie
tout le contenu d'un fichier par paquets de
1024 octets
4 - Le client reçoit certains paquets (pas tous)
5 - Fin de la connexion.

J'ai noté deux choses lors de cette opération:
- le programme "fonctionne", c'est-à-dire récupère tous les paquets lorsque serveur et client sont lancés depuis la même machine.
- tous les paquets sont bien envoyés, mais ne sont pas tous récupérés lorsque serveur et client sont distants.


Après cette brêve explication, ma supposition et mon interrogation:
Dans l'état actuel des choses, le serveur envoie ses paquets à la suite dans une boucle, et le client récupère les paquets dans une boucle, lancée en même temps. Cela me paraît plus que hasardeux quant à la fiabilité de la réception. Faut-il créer un protocole de vérification de la bonne réception des paquets? Exemple:
SERVEUR CLIENT
paquet1 ---------> ok
attends
ok<---------------- paquet1 bien reçu
paquet2----------->ok
attends

Dans le cas contraire, quelles sont les garanties de bonne réception des paquets?

Je suis très perplexe au niveau théorique du problème.
Toute aide serait grandement appréciée.

Pour finir, je propose un lien vers mes sources, mais n'étant que très peu commentées et compactées en un seul fichier, j'ai peur de rebuter à juste titre le plus courageux d'entre vous.
Lien : schrek.homelinux.org/public/mon_prog.c non valide...
PS: A compiler avec les options de standard C99 ainsi qu'en liant la librairie pthread: "gcc mon_prog.c -o mon_prog -std=c99 -lpthread"


Dernière édition par Mr_belette le Lun 7 Déc 2009 - 19:06, édité 2 fois

Mr_belette

Messages : 6
Date d'inscription : 12/07/2009
Age : 34
Localisation : Poitiers

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Protocole de transfert de fichiers en TCP/IP

Message  -ed- le Dim 6 Déc 2009 - 15:19

Mr_belette a écrit:Je rencontre un problème de fonctionnement dans une application de transfert de fichiers par TCP/IP. Ici, seulement l'aspect théorique des choses m'intéresse:
La façon de procéder dans cette application est la suivante:
Code:

1 - Le serveur se lance et écoute
2 -                                                                        Le client se connecte au serveur
3 -  Lors de la connexion, le serveur envoie
      tout le contenu d'un fichier par paquets de
      1024 octets
Directement comme ça, sans protocole d'acquittement . C'est dangereux...

Code:
4 -                                                                        Le client reçoit certains paquets (pas tous)
Pourquoi je ne suis pas surpris ?

Non seulement il faut acquitter les paquets transmis, mais de plus, il faut transmettre au préalable les informations du fichiers, comme sa taille (indispensable), son nom, sa(ses) date(s), ses droits etc.


Code:
5 - Fin de la connexion.
Dans la cas normal, sur initiative du client, une fois qu'il a tout reçu.

J'ai noté deux choses lors de cette opération:
- le programme "fonctionne", c'est-à-dire récupère tous les paquets lorsque serveur et client sont lancés depuis la même machine.
- tous les paquets sont bien envoyés, mais ne sont pas tous récupérés lorsque serveur et client sont distants.
C'est possible, oui. TCP/IP garanti qu'un paquet reçu est conforme a ce qui a été envoyé, mais si un paquet est erroné, il est perdu. C'est à un protocole supérieur de niveau 4 (comme TFTP, FTP etc.) de s'assurer que tous les paquets ont été transmis, assemblés dans le bon ordre, et de redemander les paquets manquants.


Après cette brêve explication, ma supposition et mon interrogation:
Dans l'état actuel des choses, le serveur envoie ses paquets à la suite dans une boucle, et le client récupère les paquets dans une boucle, lancée en même temps. Cela me paraît plus que hasardeux quant à la fiabilité de la réception.
Oui.
Faut-il créer un protocole de vérification de la bonne réception des paquets? Exemple:
Code:
SERVEUR        CLIENT
paquet1 ---------> ok
attends
ok<---------------- paquet1 bien reçu
paquet2----------->ok
attends
Oui, c'est un début.

Je suis très perplexe au niveau théorique du problème.
Toute aide serait grandement appréciée.
Tu te poses de bonnes questions, c'est bien.

Je n'ai pas regardé tes sources. Commence déjà par mettre au point le petit protocole que tu as envisagé. N'oublie pas de transmettre au préalable les infos du fichier...

_________________
C is a sharp tool !

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Re: Protocole de transfert de fichiers en TCP/IP

Message  Mr_belette le Lun 7 Déc 2009 - 0:31

Merci beaucoup pour ces précisions enrichissantes.

J'aboutis à une ébauche de protocole convainquant, dans lequel le serveur et le client dialoguent pour se passer les informations et vérifier leur bonne réception.
Cette conception soulève de nouvelles questions, pratiques celles-là:

Au niveau du code, comment s'assurer de la bonne réception de données?
De mon point de vue purement théorique, voici le comportement de l'application serveur pour un exemple simple de dialogue:

  1. Envoi de données
  2. Attente d'une ( réponse/déconnexion )
  3. traitement et suite

Pour l'étape 1, la fonction send() s'utilise sans commentaires, cependant, l'étape 2 reste mystérieuse à mes yeux. J'imagine que la fonction recv() doit être utilisée, mais je ne sais pas comment gérer le cas où la connexion serait interrompue. Le plus pratique serait de disposer d'un timeout, pour que la fonction rende la main après 1 ou 2 secondes d'inactivité. J'ai lu également qu'il faudrait (?) utiliser la fonction select(), et n'utiliser recv() QUE lorsque select() nous aurait prévenu de données en attente de réception.
Quoi qu'il en soit je suis perdu à ce niveau-là.

Note: Après relecture de votre site http://www.bien-programmer.fr/reseaux.php#select je croyais un instant avoir mieux compris, et puis finalement non.


Surveillance d'un flux en réception

Cet exemple est purement scolaire, car il n'a pas d'intérêt fonctionnel, étant donné que les fonctions recv() et recvfrom() sont blocantes par défaut.
Cela signifie-t-il que l'utilisation de select pour tester l'arrivage de données ne se fait pas, puisque recv() étant bloquante elle se suffit à elle-même(mais dans ce cas comment empêcher recv() d'attendre à l'infini à cause d'une déconnexion?)? Comment alors se servir de select()? Peut-on se servir de select pour qu'il rende la main ET lors d'une activité du flux surveillé ET après un temps donné?

Voilà, je ne comprends pas comment recevoir des données de manière sûre, en gérant des possibles déconnexions. Je continue de chercher sur la toile...

Mr_belette

Messages : 6
Date d'inscription : 12/07/2009
Age : 34
Localisation : Poitiers

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Protocole de transfert de fichiers en TCP/IP

Message  -ed- le Lun 7 Déc 2009 - 1:01

Mr_belette a écrit:J'aboutis à une ébauche de protocole convainquant, dans lequel le serveur et le client dialoguent pour se passer les informations et vérifier leur bonne réception.
Cette conception soulève de nouvelles questions, pratiques celles-là:

Au niveau du code, comment s'assurer de la bonne réception de données?
En testant le valeur retournée par recv().

bloqué : en attente de reception.

non bloqué :
<0 : erreur
0 : déconnexion par le distant
> 0 : nombre d'octets reçus. Si un paquet est reçu, il est garantit d'être correct. Par contre, il peut être plus grand que la taille du buffer. Tant que recv() n'est pas bloquant, c'est qu'on reçoit des données. Quand il redevient bloquant, on envoie l'acquittement et on fait les comptes. Si on a pas tout reçu, on continue d'attendre. Sinon a tout reçu, on, ferme le fichier enregistré sur disque et on se déconnecte.

De mon point de vue purement théorique, voici le comportement de l'application serveur pour un exemple simple de dialogue:

  1. Envoi de données
  2. Attente d'une ( réponse/déconnexion )
  3. traitement et suite

Pour l'étape 1, la fonction send() s'utilise sans commentaires, cependant, l'étape 2 reste mystérieuse à mes yeux. J'imagine que la fonction recv() doit être utilisée, mais je ne sais pas comment gérer le cas où la connexion serait interrompue. Le plus pratique serait de disposer d'un timeout, pour que la fonction rende la main après 1 ou 2 secondes d'inactivité. J'ai lu également qu'il faudrait (?) utiliser la fonction select(), et n'utiliser recv() QUE lorsque select() nous aurait prévenu de données en attente de réception.
Quoi qu'il en soit je suis perdu à ce niveau-là.

Note: Après relecture de votre site http://www.bien-programmer.fr/reseaux.php#select je croyais un instant avoir mieux compris, et puis finalement non.

select() peut effectivement aider à gérer les timeout qui permettent de limiter les temps d'attente. Au-dela d'une certaine durée (quelques secondes ou dizaines de secondes), on considère que la connexion ne fonctionne plus. On abandonne tout.

seect() est très puissante. C'est une fonction bloquante qui peut se débloquer sur 4 critères :
- timeout
- fin d'émission
- réception
- messagerie

En général, on se contente des critères réception et timeout. (bien lire la doc pour apprendre à les différencier).


Surveillance d'un flux en réception

Cet exemple est purement scolaire, car il n'a pas d'intérêt fonctionnel, étant donné que les fonctions recv() et recvfrom() sont blocantes par défaut.
Cela signifie-t-il que l'utilisation de select pour tester l'arrivage de données ne se fait pas, puisque recv() étant bloquante elle se suffit à elle-même(mais dans ce cas comment empêcher recv() d'attendre à l'infini à cause d'une déconnexion?)? Comment alors se servir de select()? Peut-on se servir de select pour qu'il rende la main ET lors d'une activité du flux surveillé ET après un temps donné?
Si il n'y a qu'un critère en jeu (réception, par exemple); recv() suffit. Si on met en œuvre 2 critères (réception + timeout), il faut select(). Il n'y aura pas 'double blocage' (select() puis recv() ), car si on appelle recv(), c'est que select() aura détecté au préalable une reception. L'appel à recv() ne sera donc pas bloquant.

Au bout d'un moment, il faut commencer à expérimenter ...

_________________
C is a sharp tool !

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Re: Protocole de transfert de fichiers en TCP/IP

Message  Mr_belette le Lun 7 Déc 2009 - 1:45

Merci pour toutes ces pistes et éléments de réflexion.

J'explore en ce moment la piste du select() + recv(). Ca semble fonctionner, mais je vais pousser les tests plus loin et tenter de finir mon petit programme.
Je pense en effet qu'en mettant la main à la pâte je vais finir par comprendre.

Bonne soirée et merci encore,

Matthieu

Mr_belette

Messages : 6
Date d'inscription : 12/07/2009
Age : 34
Localisation : Poitiers

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Protocole de transfert de fichiers en TCP/IP

Message  Mr_belette le Jeu 10 Déc 2009 - 13:57

C'est encore moi,

J'ai réalisé des tests simple d'envois d'une chaîne de 10 caractères, d'abord seulement sur ma machine, et ensuite entre deux machines distantes sans problème. J'ai utilisé select() pour cela, et j'en suis très content.
Pour être bien sûr du fonctionnement des envois/réceptions j'ai testé également une façon de faire volontairement chaotique :
Le serveur envoie 6 (pourquoi pas 6 fois?) fois la chaîne à la suite dans une boucle, et le client tente de réceptionner 6 fois la chaîne à la suite dans une boucle également.
Résultat catastrophique, normal. (bien que une fois ce soit passé...).

Donc ma conclusion concernant l'envoi de fichiers:
Après chaque envoi avec send(), j'estime qu'il faut absolument attendre une réponse pour vérifier que la réception s'est bien passée, sinon on ne peut être sûr du bon déroulement. Est-ce juste?

Finalement, et c'est un avis tout à fait personnel, dans tous les tutoriels et cours vus sur internet concernant le C et les sockets, jamais personne ne met l'accent sur le facteur temps, et moi c'est cela qui m'a posé problème. En effet, cela peut sembler basique, mais une application est une suite d'instructions à effectuer dans le temps. Dans le cas d'un programme autonome, aucune synchronisation n'est nécessaire et la question ne se pose pas vraiment: les instructions défilent une à une. Par contre, dans le cas d'une communication, il faut obligatoirement une synchronisation des différentes applications dans le temps. C'est en effet une assertion extrêmement triviale, mais je n'ai pas honte de dire que c'est le fait de ne pas en avoir pris conscience plus tôt qui m'a fait perdre en temps fou. En fait c'est surtout le manque de connaissance des fonctions permettant de gérer cette synchronisation qui m'a fait défaut.
On parle toujours d'envoi de données, de réception de données... puis on passe au pseudo code et aux fonctions, recv(), send(), mais peut-être faudrait-il mettre plus l'accent sur les moyens de synchronisation. Basiquement, c'est recv() qui s'en charge, mais c'est une fonction bloquante, et en cas de mal-fonctionnement elle peut tourner en boucle, donc elle n'est pas à utiliser telle quelle... on se voit alors obligé d'utiliser select(), ou un thread... mais ce ne sont pas des options, c'est dans la grande mojorité des cas une obligation, non?

Voila mon opinion, sûrement bien naïve du reste.

Matthieu S

Mr_belette

Messages : 6
Date d'inscription : 12/07/2009
Age : 34
Localisation : Poitiers

Voir le profil de l'utilisateur

Revenir en haut Aller en bas

Re: Protocole de transfert de fichiers en TCP/IP

Message  -ed- le Jeu 10 Déc 2009 - 14:36

Mr_belette a écrit:J'ai réalisé des tests simple d'envois d'une chaîne de 10 caractères, d'abord seulement sur ma machine, et ensuite entre deux machines distantes sans problème. J'ai utilisé select() pour cela, et j'en suis très content.
Pour être bien sûr du fonctionnement des envois/réceptions j'ai testé également une façon de faire volontairement chaotique :
Le serveur envoie 6 (pourquoi pas 6 fois?) fois la chaîne à la suite dans une boucle, et le client tente de réceptionner 6 fois la chaîne à la suite dans une boucle également.
Résultat catastrophique, normal. (bien que une fois ce soit passé...).

Donc ma conclusion concernant l'envoi de fichiers:
Après chaque envoi avec send(), j'estime qu'il faut absolument attendre une réponse pour vérifier que la réception s'est bien passée, sinon on ne peut être sûr du bon déroulement. Est-ce juste?
Oui.

Finalement, et c'est un avis tout à fait personnel, dans tous les tutoriels et cours vus sur internet concernant le C et les sockets, jamais personne ne met l'accent sur le facteur temps, et moi c'est cela qui m'a posé problème. En effet, cela peut sembler basique, mais une application est une suite d'instructions à effectuer dans le temps. Dans le cas d'un programme autonome, aucune synchronisation n'est nécessaire et la question ne se pose pas vraiment: les instructions défilent une à une. Par contre, dans le cas d'une communication, il faut obligatoirement une synchronisation des différentes applications dans le temps.
Oui, en effet, quand on étudie les problèmes de communication, on apprend à gérer le facteur temps. Ne pas oublier qu'un langage de programmation est un outil, un moyen au service d'un projet et non une fin en soi. Oui, le projet doit être bien défini, et oui, dans un projet communiquant de niveau ISO 4 ou plus, on doit mettre en œuvre un protocole qui définit, entre autre, la manière dont est géré la régulation de flux (trame par trame ou par fenêtre glissante etc.). La littérature sur le sujet abonde, mais encore une fois elle n'a rien à voir avec les langages de programmation ...

C'est en effet une assertion extrêmement triviale, mais je n'ai pas honte de dire que c'est le fait de ne pas en avoir pris conscience plus tôt qui m'a fait perdre en temps fou. En fait c'est surtout le manque de connaissance des fonctions permettant de gérer cette synchronisation qui m'a fait défaut.
C'est surtout le manque de discernement entre fin et moyen... Tu manques de connaissances générales sur ce qu'est la transmission de données (les réseaux, quoi). Le langage C et les bibliothèques de sockets ne sont qu'un moyen (de relativement bas niveau : couches ISO 2 à 3) qui permettent de réaliser des transmissions de données.

On parle toujours d'envoi de données, de réception de données... puis on passe au pseudo code et aux fonctions, recv(), send(), mais peut-être faudrait-il mettre plus l'accent sur les moyens de synchronisation. Basiquement, c'est recv() qui s'en charge, mais c'est une fonction bloquante, et en cas de mal-fonctionnement elle peut tourner en boucle,
Non. en cas d'erreur, comme déjà indiqué, elle retourne un code <= 0. Elle devient non bloquante, et on doit alors sortir de la boucle de réception en signalant l'erreur à qui de droit.
donc elle n'est pas à utiliser telle quelle...
Dans les cas simples, si, c'est possible...
Code:
on se voit alors obligé d'utiliser select(), ou un thread... mais ce ne sont pas des options, c'est dans la grande mojorité des cas une obligation, non?
Dès qu'il faut gérer simultanément l'attente de plusieurs évènements, oui.
Voila mon opinion, sûrement bien naïve du reste.
Tes remarques sont pleines de bon sens et tout à fait pertinantes.

_________________
C is a sharp tool !

-ed-
Admin
Admin

Messages : 289
Date d'inscription : 26/05/2008
Age : 60
Localisation : Paris 6eme arrondissement (75, France)

Voir le profil de l'utilisateur http://bien-programmer.fr

Revenir en haut Aller en bas

Re: Protocole de transfert de fichiers en TCP/IP

Message  Contenu sponsorisé Aujourd'hui à 21:21


Contenu sponsorisé


Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum