Protocole de transfert de fichiers en TCP/IP
2 participants
Page 1 sur 1
Protocole de transfert de fichiers en TCP/IP
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"
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 :
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 : 41
Localisation : Poitiers
Re: Protocole de transfert de fichiers en TCP/IP
Directement comme ça, sans protocole d'acquittement . C'est dangereux...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
Pourquoi je ne suis pas surpris ?
- Code:
4 - Le client reçoit certains paquets (pas tous)
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.
Dans la cas normal, sur initiative du client, une fois qu'il a tout reçu.
- Code:
5 - Fin de la connexion.
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.
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.
Oui.
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, c'est un début.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
Tu te poses de bonnes questions, c'est bien.Je suis très perplexe au niveau théorique du problème.
Toute aide serait grandement appréciée.
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...
Re: Protocole de transfert de fichiers en TCP/IP
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:
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.
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...
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:
- Envoi de données
- Attente d'une ( réponse/déconnexion )
- 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.
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é?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.
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 : 41
Localisation : Poitiers
Re: Protocole de transfert de fichiers en TCP/IP
En testant le valeur retournée par recv().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?
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.
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.
De mon point de vue purement théorique, voici le comportement de l'application serveur pour un exemple simple de dialogue:
- Envoi de données
- Attente d'une ( réponse/déconnexion )
- 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.
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).
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.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é?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.
Au bout d'un moment, il faut commencer à expérimenter ...
Re: Protocole de transfert de fichiers en TCP/IP
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
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 : 41
Localisation : Poitiers
Re: Protocole de transfert de fichiers en TCP/IP
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
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 : 41
Localisation : Poitiers
Re: Protocole de transfert de fichiers en TCP/IP
Oui.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, 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 ...
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 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.
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.
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.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,
Dans les cas simples, si, c'est possible...donc elle n'est pas à utiliser telle quelle...
- 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?
Tes remarques sont pleines de bon sens et tout à fait pertinantes.Voila mon opinion, sûrement bien naïve du reste.
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum