1

Hello,

Avant de me lancer dans quelques expériences réseau, je me pose quelques questions. Il me semble avoir vu que la fonction de base pour lire des données sur une socket, sous Windows, était "recv" ; or cette fonction est par défaut bloquante, d'où le besoin de passer par des threads. Jusque là, rien de bien compliqué.

En revanche, quand arrive la fin de l'application, il faut terminer tous ces threads, et sauf erreur de ma part il n'est pas possible de les terminer proprement (signal ou autre) puisque si le thread est en attente de données et que rien n'arrive il restera bloqué indéfiniment. Utiliser "TerminateThread" n'est pour autant pas une solution, puisque ça ne libère pas les éventuelles ressources qu'aurait pu utiliser le thread. On peut envisager de préallouer toutes les ressources et de faire en sorte que le thread n'alloue absolument rien, mais c'est quand même une sacré contrainte (et ça n'enlève pas le fait que TerminateThread soit un peu violent).

D'un autre côté, on pourrait aussi rendre les sockets non bloquantes, de façon à pouvoir signaler à tout moment à un thread qu'il doit s'arrêter et lui permettre de le faire proprement. Mais cela implique une boucle qui appelle régulièrement un "recv" non bloquant, et je suppose que pour ne pas pomper tout le CPU il faudrait coller un Sleep() quelque part. Du coup, on introduit un léger lag au niveau de la réception des données (avec un Sleep(200), il faut potentiellement 200ms pour que le programme se rende compte qu'il a reçu des données), à moins qu'il existe une solution de lecture "bloquante mais pas trop longtemps" qui permette au programme de se mettre en attente de données pour un certain temps et d'abandonner si rien n'est reçu.

Bref, quelle est pour vous la bonne méthode, puisque j'imagine qu'il en existe au moins une qui n'a pas tous les désavantages que je viens de citer ?

Merci smile
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

2

En Java, il suffit de faire un close() sur le socket concerné pour que les lectures bloquantes faite dessus soient interrompues.
Peut-être que le fonctionnement est le même en C.
avatar

3

Il me semble que c'est le cas, en effet.
avatar
<<< Kernel Extremis©®™ >>> et Inventeur de la différence administratif/judiciaire ! (©Yoshi Noir)

<Vertyos> un poil plus mais elle suce bien quand même la mienne ^^
<Sabrina`> tinkiete flan c juste qu'ils sont jaloux que je te trouve aussi appétissant

4

Ah oui, après vérification ça semble être le cas, par contre le problème se pose quand même pour "listen" (qui n'a pas l'air d'avoir ce comportement).
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

5

Pourquoi ne pas utiliser une bibliothèque de plus haut niveau qui t'offre un mécanisme de gestion d'événements avec des méthodes non bloquantes (comme Qt 4 par exemple ^^).
avatar
la Nature nous montre seulement la queue du lion. Mais je suis certain que le lion a qui elle appartient pense qu'il ne peut pas se révéler en une fois en raison de son immense taille.

- Fondateur de Ti-Gen -: http://www.tigen.org

- Membre du Groupe Orage Studio -: http://oragestudio.free.fr/

- Mon site perso -: http://tisofts.free.fr

Projets TI68K en cours:
GFA-Basic = http://www.tigen.org/gfabasic
Arkanoid.
PolySnd 3.0.

6

Parceque je cherche justement à faire fonctionner tout ça moi-même, il n'y a pas de vrai projet derrière.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

7

-- non rien --

enfin si:

Le temps d'attente sur une recv n'est pas "INFINITE", il y a toujours un timeout, apres si tu kill toutes les sockets/thread, c'est souvent car tu quitte l'application, et fermer une socket/thread de maniere brutale n'est pas forcement très grave.

Apres effectivement il reste le moyen de faire des sockets non bloquantes, mais ce n'est pas très efficaces, car tu vas devoir faire du polling, et faire des attentes, donc tu va limiter le débit car tes temps d'attentes auront lieu à chaque reception (ou alors il faut faire du code pas forcement propre, ou tu va attendre si tu as rien recu et une attente dans le cas contraire, mais meme dans ce cas, tu risque de limiter le débit)

Sinon le close sur une socket devrait normalement arreter le "recv" (edit: ça devrait normalement marcher aussi pour listen, si on close la socket, la socket utilisé par le listen devient invalide..)

Je regarde ce soir dans mes codes pour voir comment je faisais...

Le problème c'est que certains de ces parametres dépendent de l'implémentation... Et le timeout doit pouvoir être configurable sur certaines d'entre elles
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

8

Je ne sais pas si c'est le cas pour les sockets, mais pour d'autres fonctions Windows il y a deux façons (grosso modo équivalentes) de gérer ce genre de cas : en plus des fonctions bloquantes, il existe des fonctions non bloquantes qui déclenchent un événement ou qui envoient un message lorsqu'il se passe quelque chose d'"intéressant". L'avantage par rapport aux fonctions bloquantes, c'est qu'aussi bien avec les événements que les messages, on peut surveiller plusieurs conditions à la fois sans utiliser de temps CPU. Donc en plus de la condition principale, on peut prévoir une condition pour terminer le thread proprement. Quand l'application doit quitter, le thread principal a juste à envoyer les messages ou déclencher les événements, et à attendre que chaque thread secondaire se termine.

La fonction WSAWaitForMultipleEvents() me laisse supposer que ça marche aussi comme ça pour les sockets, par contre tu risques d'avoir à utiliser les fonctions natives Windows comme WSARecv() au lieu d'une fonction standard comme recv().
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

9

si c'est que ça c'est pas bien grave, je jetterai un coup d'oeil ^^

sinon, quelqu'un aurait des liens vers des explications un peu détaillées sur le fonctionnement général des sockets ? par exemple en essayant de simuler un proxy socks5 je me suis rendu compte que deux "send" n'étaient pas du tout équivalent à un seul "send" contenant bout à bout les données des deux, pourtant intuitivement ça me semblait logique (du coup qu'est-ce qui "sépare" les deux flux de données ?)
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

10

Zephyr (./9) :
(du coup qu'est-ce qui "sépare" les deux flux de données ?)


La pile TCP/IP en elle même.

Si tu envoie en morceau, il faut que tu les "tags" pour en connaître l'ordre, sinon c'est la pile qui reordonne les packets (c'est pour ça que le protocol HTTP par exemple tag les blocs pour eviter de recevoir de maniere désordonné)
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

11

"tag" les blocs? quel tag? le numéro de séquence?

12

heu mais du coup à mon niveau je n'ai aucun moyen de différencier deux blocs volontairement séparés (par ce "tag") d'un seul bloc que j'aurais reçu en deux recv consécutifs parceque trop gros pour tenir en une seule fois dans mon buffer ?
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

13

squalyl (./11) :
"tag" les blocs? quel tag? le numéro de séquence?

Par tagguer, je parle d'ajouter une en tete avec les parametres que l'on veux (ie faire un protocole) comme on le ferrais en POP, HTTP ou je ne sais quel protocole reseau)

./12: ben tu met en en-tete de chaque blocs deux champs, un numero "unique" (d'une série de bloc) et un numero identifiant la position dans la série (je sais pas si je suis clair)

C'est un des seul moyens si tu veux être sur de l'ordre de tes blocs si tu découpe toi même, sinon tu laisse le faire a la pile TCP et tu ne morcele pas toi meme les donnée (ie tu les envoies d'un bloc)

Le tag n'est pas a envoyer entre chaque bloc, mais doit être ajouté dans les données (ie: tu encapsule les donnée)

(désolé si je suis pas clair)
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

14

Rien compris grin

Mais je suis pas sûr que ça réponde à ma question, donc dans le doute je la reformule autrement : d'après ce que tu expliques, cette segmentation est gérée par un système plus bas niveau que ce à quoi j'ai accès. Du coup quand je reçois deux blocs de données, je suis incapable de savoir s'il s'agit d'un seul bloc coupé en deux ou de deux blocs segmentés par ce mécanisme. La solution consiste d'après toi à réimplémenter de mon coté un système me permettant d'identifier les bouts à "recoller". D'un point de vue conception ça me semble très étrange : on me masque une caractéristique bas niveau (la segmentation des blocs) mais on m'oblige à implémenter mon propre mécanisme pour que ce que je manipule reste cohérent. Tu es vraiment sûr de toi ?
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

15

Si le découpage est fait d'un niveau plus bas, tu ne reçois qu'un bloc et non deux, si tu en reçoit explicitement deux, il y a plusieurs raisons possible :

- Soit ton bloc mémoire est trop petit
- Soit c'est l'émetteur qui a découpé de manière "haut niveau" les données (donc pas découpé par la pile TCP/IP, mais lié au protocole au dessus genre HTTP, POP, L33TPROT, etc...)

Je suis clair cette fois ? grin wink

En très gros: si TCP/IP découpe un paquet, c'est transparent pour toi
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

16

oui mais justement : comment puis-je savoir si c'est l'émetteur qui a volontairement scindé ses données en deux blocs (auquel cas je les laisse tels quels) ou si c'est une contrainte technique genre taille du buffer (auquel cas je pourrais être tenté de recoller les deux bouts) ?
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

17

TCP ne transporte pas des « paquets », mais un flux. Il n'y a pas de morceaux avec un début et une fin.

Que tu fasses deux send ou un seul gros ne devrait rien changer, ils sont l'un derrière l'autre et ordonnés. Seulement, tu ne peux pas compter sur le découpage. Suivant la version de TCP, l'émetteur peut attendre de pouvoir remplir une trame avant d'envoyer les données, ou envoyer dès qu'il peut. Dans le second cas, tu reçois les données en deux fois (sauf si tu lis après que tu aies reçu les deux parties, dans ce cas, elles peuvent être recollées).

Si tu veux un système en paquets, il faut te les faire toi-même : soit ils ont toujours la même taille, et donc tu lis par morceaux de cette taille (et tu continues à lire, tu attends la suite, si tu reçois moins pour avoir le paquet entier avant de le traiter). Soit, tu te fais ton protocole à toi. Un simple serait d'envoyer un entier de la taille que tu veux (mais fixée) au début de chaque paquet pour en indiquer sa taille. Et tu lis jusqu'à atteindre cette taille (et seulement cette taille) pour avoir le paquet entier. Pour obtenir le paquet suivant, tu lis la taille (elle est transmise au début du paquet) et tu lis le paquet...

Tu peux bien sûr te faire un protocole plus compliqué grin

Voilà, j'espère avoir été clair, mais je n'en suis pas sûr grin
avatar

18

Justement, intuitivement je pensais que ça fonctionnait de la façon que tu décris (un flux de données sans aucune notion de début ou de fin). Mais en partant sur ce principe, envoyer "AAA" puis "BBB" en deux send ou envoyer "AAABBB" en un seul devrait être strictement équivalent, non ? Pourtant je me suis rendu compte en voulant simuler un proxy socks5 qu'il me fallait envoyer dans un premier temps les données préliminaires (annonces des méthodes d'authentification, échange des addresses, etc), puis dans un send séparé les données à "proxifier". Si je commence à échanger des données dans le même send que celui qui finalise la procédure d'authentification, ça ne fonctionne pas, ce qui semble contredire cette histoire de "flux sans début ni fin" :/
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

19

Il maque peut-être quelque chose entre ton « AAA » et ton « BBB » qui est compensé par le fait de tomber sur une fin de paquet TCP...

Ou peut-être qu'il faut attendre une réponse ou un temps entre l'entête et le corps... Le serveur est peut-être mal programmé aussi et ne respecte peut-être pas TCP ^^
avatar

20

ne respecte pas TCP? trifus

Zephyr: le comportement différent que tu décris selon le découpage de blocs me semble étrange. Un truc de ce genre m'est déja arrivé avec un serveur IRC, où on doit lire des lignes de texte dans un flux, etc, et en fait c'était plutot dans mes données qu'il y avait des problèmes, style fins de lignes bizarres, ou timeout, ou tailles de buffers qui peuvent faire des conneries si tu fais un send() plus gros que le buffer d'envoi et que la pile tcpip fait de la merde, etc.

Parce que TCP fournit un flux transparent sans discernement de paquets, ça, c'est sûr.

21

Je voulais simuler un serveur socks5 ; d'après la RFC il ne manque rien entre "AAA" (la fin des informations d'authentification) et "BBB" (les données à transmettre), et le client est Firefox donc l'erreur a bien plus de chances de venir de moi, sans que je sache pourquoi ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

22

squalyl (./20) :
ne respecte pas TCP? trifus.gif
Bah oui, il ne faut pas considérer ce qui arrive comme des paquets. Il faut lire seulement les données dont on a besoin, celles qui restent dans les tampons serviront par la suite. Ne pas respecter TCP, c'est lire comme si c'était un paquet et donc lire tout ce qu'il y a dans les tampon et n'utiliser que le début, et jeter le reste. Bien sûr, ce n'est pas vraiment un non respect de TCP, mais plutôt une incompréhension du type de donnée transporté.

Zephyr, où se situe le problème ? Entre Firefox et ton proxy ? Ou entre ton proxy et un serveur HTTP ? Ou autre part ?
Ce que tu programmes, c'est bien le proxy ? « AAABBB », c'est ce que tu envoies ou ce que tu reçois ? Et de ou à qui ?

Peut-être que tu as déjà écrit tout ça, mais ce n'est pas très précis.
avatar

23

Il ya moyen normalement de savoir si ce qu'on a récupéré avec recv corresond a tout ce qui est en attente ou non, ça remonte un peu trop (pour moi) mais c'est trouvable...
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

24

Zephyr, es-tu sûr que tout « AAABBB » est parti ?
Il faut vérifier la valeur retournée par send...

Pour en revenir au problème des fonctions bloquantes, tu peux utiliser la fonction select qui permet de définir un temps maximal d'attente.
avatar

25

Vous êtes sur qu'il s'agit d'un topic algorithmique et optimisation???

Je suis un peu dégouté de voir que personne ne répond à une question sql+algo mais plutôt à une question de programmation réseau bas niveau dans la section "algo".
[/HS]
Tout ce qui passe pas par le port 80, c'est de la triche.

26

Il n'y a pas de forum réseau, et le sujet porte sur le fonctionnement général des sockets et la façon de les utiliser... même si c'est pas exactement de l'algo, c'est pas encore trop éloigné. Par contre pour faire ce genre de remarques ça serait cool que tu ailles ailleurs parceque pour le coup c'est hors-sujet.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

27

Bah c'est pas une reproche pour toi. Je pars du constat qu'on est dans le forum algo/optimisation et que tout le monde répond à une question de programmation réseau bas niveau...
Donc je le dis à tout le monde et pas qu'à toi, je sais que c'est HS, d'où la balise /HS de mon précédent post. Enfin passons. Vraiment [/HS] cette fois ci.
Tout ce qui passe pas par le port 80, c'est de la triche.

28

Si les gens ont vu ce topic ils ont vu le tien, et si pour l'instant il n'y a pas de réponse il faut croire que c'est parceque personne n'a de réponse ou que ta question est mal posée.

Bref, Thepro pour répondre à ta question tous les octets ont été envoyés mais je viens de me rendre compte que Firefox affichait encore sa petite animation "en cours de réception" (le logo ajax-like qui tourne) même après avoir reçu et affiché ce que je lui envoyais. Il doit attendre quelque chose d'autre que j'ai oublié de lui envoyer, donc le test est incomplet ; je cherche ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

29

t'as pensé au keep-alive? si y'a pas, il faut clore la connexion smile