Problème de réception TCP - C#/.NET managed - Programmation
Marsh Posté le 02-04-2007 à 21:08:06
Hello
Dans ma boucle de réception, à un certain moment, la fonction 'Receive' de mon socket de réception, normalement bloquante, retourne directement en me renvoyant un nombre de bytes inférieur à celui demandé. |
Il faut que tu comptes le nbr de bytes recu à chaque receive et que tu boucles tant que tu n as pas recu le nombre d octets attendus.
Ce nombre est toujours soit 404 soit 0. Dans le cas où je reçois 0 byte, ma connexion est irrécupérable et la fonction Receive me retournera toujours 0. |
Aucune idée d'un tel bug (0 = echec), mais 404 ne serait pas le nbr de bytes que tu demandes de lire (parametres passé au receive) ??
J'ai l'impression que ce phénomène est du à un débordement du buffer de réception lorsque windows prend la main trop longtemps. Est-ce possible? |
Chaque fois que j ai eu de tels poblemes et que j ai mis ca sur le compte des trames ou des longueurs de buffer, je me suis trompé et l'erreur venait de moi. Donc, peu de chance ...
Sinon, il y a aussi les network stream qui sont simples à utiliser . Tu peux essayer avec aussi.
En esperant t avoir un peu aider ...
Marsh Posté le 02-04-2007 à 22:23:00
Merci beaucoup pour ta réponse !
Le nombre de bytes que je désire lire est 528.
Citation : Il faut que tu comptes le nbr de bytes recu à chaque receive et que tu boucles tant que tu n as pas recu le nombre d octets attendus. |
C'est quand même bizarre pour une fonction bloquante... Normalement il doit attendre d'avoir tout les bytes demandés non...
Lorsque la fonction Receive() retourne 0 byte, là j'ai beau boucler et attendre, elle me retournera toujours 0 byte...
Citation : Sinon, il y a aussi les network stream qui sont simples à utiliser . Tu peux essayer avec aussi. |
C'est ce que j'avais utilisé au début. Mais la classe masquait le problème décrit ci-dessus.
Citation : Chaque fois que j ai eu de tels poblemes et que j ai mis ca sur le compte des trames ou des longueurs de buffer, je me suis trompé et l'erreur venait de moi. Donc, peu de chance ... |
Quelle genre d'erreur pourrait causer ce phénomène?
Encore merci pour ta réponse.
A+
BigBulle
Marsh Posté le 03-04-2007 à 17:24:02
Je suis en train de finir une class hyper simplifié mais pratique pour la communication réseau, si tu es intéressé je pourrais te la refiler.
Au passage ça me permettra de me faire allumer par quelques gurus histoire que je puisse l'améliorer davantage...
Marsh Posté le 04-04-2007 à 11:24:10
Citation : Je suis en train de finir une class hyper simplifié mais pratique pour la communication réseau, si tu es intéressé je pourrais te la refiler. |
Cool tiens moi au courant .
J'ai encore cherché sur le Net et j'ai pu lire que la fonction Receive() n'attend pas spécialement d'avoir tous les bytes demandés pour retourner...
Mais je n'ai pas encore compris qu'est ce qui fait que la fonction Receive() retourne...
Est-ce lors de la réception d'un segment de donnée TCP?
Je ne pense pas...
Quant à la réception de 0 byte ceci est apparement simplement du au fait que le client s'est déconnecté.
A+
Marsh Posté le 04-04-2007 à 12:45:27
Voilà tu trouveras ci-dessous en exclusivité ma ClassComm.
Je ne sais pas si tu es en C# ou en VB.net, en tout cas la class elle est en VB.net et tu sais comme moi que ça n'y change rien...
Fonctionnement :
} Connexion
- on définit grâce au constructeur si c'est un serveur qui écoute ou bien un client qui va se connecter à un serveur
- si instanciée en serveur, un évenement prévient lorsqu'une connexion arrive, et donne le socket client
- si instanciée en client (avec les infos de connexion en paramètre), un évenement prévient si c'est connecté ou non
} Parlote
# les messages sont des classcomm.commMessage (structure perso pour simplifier la comm réseau)
- pour envoyer un message, on utilise Send qui prend en paramètre un Ordre (string) et un Message (string)
- pour recevoir des messages, il suffit de tester de temps en temps MsgCount : si y'en a 0 c'est que y'a pas de commmessage à consommer, sinon c'est que y'en a le nombre indiqué en attente d'être lu, grâce à ReadNextMsg qui renvoie un commMessage
} L'event ProblemDetected
- renvoit ErrorType.connection_failed si un client n'a pas su se connecter à un serveur donné
- renvoit ErrorType.seems_disconnected si on est vraisemblablement déconnecté (erreur pendant une transmission par exemple)
- renvoit ErrorType.receive_an_empty_message si un buffer de 0 byte est reçu, ce qui n'est pas normal du tout (j'ai failli merger cette erreur avec la précédente en fait... car c'est tout comme !)
} Fermeture
- pour fermer un serveur ou une connexion ouvert, utilisez la méthode Dispose
Pourquoi avoir utilisé une structure perso (commMessage) pour l'envoi et la réception ?
L'utilisateur de cette classe simplifiée n'a pas à s'inquiéter de ce qu'il envoit et comment il l'envoit. Il envoit juste.
A la réception on reçoit donc un commMessage, on regarde l'ordre (par exemple avec un select case) et on interprete donc le message correctement, l'ordre nous renseignant sur ce qu'on doit faire du message (exemple bidon : est-ce que c'est l'âge du gars, son nom ou bien son prénom ?)
Pourquoi ne pas avoir mis en event un message arrivant ?
Parceque c'est le problème qui me reste à résoudre : tous les events (y'en a pas beaucoup quand même) sont renvoyé dans un thread à part à cause des callbacks des sockets, donc on peut pas agir sur une interface à partir des events de la class.
Alors j'ai jugé plus souple de mettre les messages arrivant dans une file d'attente FIFO (first in first out), qui sera par exemple checké par l'utilisateur à l'aide d'un Timer 100ms, pour de la comm réseau, c'est pas un souci.
C'est quoi idCode dans le commMessage ?
La classe est consciencieuse : quand elle envoit un message, avant de pouvoir en envoyer un nouveau, elle attend d'avoir la confirmation que le message précédent a bien été reçu. Chaque message a un idCode unique, et ce code sert d'accusé de réception. Quand la class reçoit un message, elle renvoie l'idCode à l'expéditeur pour dire OK, sinon le dit expéditeur renverra sans cesse le message au bout d'un laps de temps (timeout définit au constructeur) jusqu'à avoir la confirmation que c'est bien reçu.
Pas d'inquiétude, les messages n'arrivent pas en double, le mécanisme est bien géré, tout est vérifié.
Pas d'inquiétude non plus, les nouveaux messages demandés à être envoyé entre un envoi précédent et son propre accusé de réception sont mis en file d'attente pour être envoyé après, donc rien n'est perdu.
Au final on a une class bien aboutie qui gère bien ses comm réseau à la place de l'user.
Bref, ne pas prendre garde à l'idcode, c'est pour info seulement, au cas où on en aurait besoin pour autre chose... sinon pas touche !!
EXEMPLE CONCENTRÉ DANS UNE FORM
Citation : |
Voici donc ma classComm :
|
A vos critiques.
Merci de ne pas s'approprier odieusement mon travail !
Celiphane
14h58 : je viens de mettre à jour le code suite à une erreur que j'ai trouvé dans l'implémentation du dispose
15h54 : Nouvelle mise à jour : détection d'erreur ajoutée sur certains points et changement de certains code erreur
NB : puisque je m'apprête à utiliser la class dans des applis pro, je vais ouvrir un topic séparé pour avoir des retours
Marsh Posté le 02-04-2007 à 16:12:11
Bonjour à tous ,
Je développe actuellement un programme qui joue entre autre le rôle de serveur TCP et j'ai un gros problème lors de la réception des données envoyées par le client:
Dans ma boucle de réception, à un certain moment, la fonction 'Receive' de mon socket de réception, normalement bloquante, retourne directement en me renvoyant un nombre de bytes inférieur à celui demandé.
Ce nombre est toujours soit 404 soit 0. Dans le cas où je reçois 0 byte, ma connexion est irrécupérable et la fonction Receive me retournera toujours 0.
Par contre, lorsque je reçois 404 bytes, je reçois parfois les suivants au Receive suivant...
J'ai l'impression que ce phénomène est du à un débordement du buffer de réception lorsque windows prend la main trop longtemps. Est-ce possible?
Pourquoi la fonction Receive retourne simplement sans balancer d'exception?
Le programme client étant programmé par quelqu'un d'autre, je n'y ai pas directement accès. Mais je suis quasi sûr qu'il continue à envoyer ses données.
J'espère que mes explications sont assez claires
Un tout grand merci d'avance ,
BigBulle.