begin process at 2012 02 14 03:21:29
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Réseau & Internet

 > ÉVITER QUE LES PAQUETS SE MÉLANGE LORS DE L'ENVOIE AVEC WINSOCK

ÉVITER QUE LES PAQUETS SE MÉLANGE LORS DE L'ENVOIE AVEC WINSOCK


 Information sur la source

Note :
5 / 10 - par 2 personnes
5,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Réseau & Internet Niveau :Débutant Date de création :05/08/2003 Date de mise à jour :25/11/2003 19:02:38 Vu :5 027

Auteur : gabchampagne

Ecrire un message privé
Site perso
Commentaire sur cette source (36)
Ajouter un commentaire et/ou une note

 Description

j'ai trouver une solution à ce problème et je voudrai la partager avec vous.  

Source

  • '1- vous devez mettre sa dans la feuille où il y a le contrôle winsock
  • Private pile As New Collection
  • private rendu as long
  • Public Sub Vider_Pile()
  • Set pile = New Collection
  • End Sub
  • '2- créer un Timer, donné la valeur 1 à la propriété interval et méttez sa dans 'son evenement Timer :
  • dim encour as long
  • If pile.Count = 0 Then
  • Else
  • If pret = False Then
  • rendu=rendu+1
  • encour=rendu
  • socket.SendData pile.Item(encour)
  • pile.Remove encour
  • rendu=rendu-1
  • End If
  • End If
  • '3- dans votre controle winsock, dans l'evenement send complete marquez ca
  • pret = False
  • '4-dans ce meme controle winsock, dans l'évenement sendprogress marquez sa
  • pret = True
  • '5- quand vous devez envoyer des données marquez sa à la place
  • 'de .senddata
  • pile.Add "Données"
'1- vous devez mettre sa dans la feuille où il y a le contrôle winsock
Private pile As New Collection
private rendu as long
Public Sub Vider_Pile()
Set pile = New Collection
End Sub

'2- créer un Timer, donné la valeur 1 à la propriété interval et méttez sa dans 'son evenement Timer :
dim encour as long
If pile.Count = 0 Then
Else
If pret = False Then
rendu=rendu+1
encour=rendu
socket.SendData pile.Item(encour)
pile.Remove encour
rendu=rendu-1
End If
End If

'3- dans votre controle winsock, dans l'evenement send complete marquez ca
pret = False

'4-dans ce meme controle winsock, dans l'évenement sendprogress marquez sa

pret = True 

'5- quand vous devez envoyer des données marquez sa à la place 
'de .senddata

pile.Add "Données" 

 Conclusion

c tout. dites moi vos commentaires  


 Sources du même auteur

DÉTERMINER DE COMBIENS DE PIXELS VOTRE CURSEUR C'EST DÉPLACÉ
Source avec Zip Source avec une capture TESTER VOTRE JOYSTICK OU VOTRE VOLANT POUR ORDI SIMPLEMENT
Source avec Zip Source avec une capture LISTER LES PÉRIPHÉRIQUES, LES CODECS ET LES PROTOCOLES RÉSEA...
Source avec Zip SERVEUR HTTP QUI SUPPORTE PARFAITEMENT LE PROTOCOLE HTTP
DÉTERMINER SI UN URL EST VALIDE

 Sources de la même categorie

Source avec Zip Source avec une capture GESTIONNAIRE DE TÉLÉCHARGEMENT, AVEC REPRISE ET MULTITHREADI... par Madx23
Source avec Zip Source avec une capture CONVERTIR DU TEXTE RTF EN CODE HTML ET VICE-VERSA par vicosta
Source avec Zip Source avec une capture DICTIONAIRE TEXT/AUDIO/VISUELLE ANGLAIS AVEC WEBBROWSER CONT... par majnounmajda
Source avec Zip Source .NET (Dotnet) NSLOOKUP EN VB.NET OU COMMENT FAIRE UNE REQÛETE DNS EN PRÉCI... par ShareVB
Source avec Zip Source avec une capture MINI SEVEUR HTTP AVEC INTERFACE GRAPHIQUE ET IMPLÉMENTATIONS... par lemout

Commentaires et avis

Commentaire de neria le 05/08/2003 08:46:37

Salut Gab !
Je pense que j'ai trouvé une solution autant efficace et moins longue et contraignante que celle là :
Winsock.senddata data             'Envoie le paquet
DoEvents         'Attent que winsocke ait envoyé son paquet pour continuer
Voilà, chez moi ça fonctionne très bien !
@+

Commentaire de THXTHECATZ le 05/08/2003 10:57:13

Personellement, je déclare un Boolean public, qui passe a true lorque l'évenement Winsock_SendComplete() est déclenché, et dans ma procédure d'envoi, je place un:

Do while not LeBooleanEnQuestion

   DoEvents

Loop

Ce qui me permet d'être sûr à 100% que le paquet est envoyé avant de transmettre le suivant.

Voila c'est tout :)

Commentaire de Greengold le 05/08/2003 12:03:34

salut,
un message pour neria : ta solution ne marche pas tout le temps.

Si tu fais ce code par exemple :
For i = 1 to 10
     DoEvents
     winsock.sendData i
     DoEvents
Next i

Tu n'enveras pas 10 trames de 1 caractère mais une trame de 10 caractères.
En fait le DoEvents est inopérant dans ce cas là parce que windows reprend la main sur ce code pour l'optimiser.
Il ne faut pas faire de boucle ! Malgré le DoEvents l'exécution machine de ce code est trop rapide, c'est pourquoi je passe par un timer à 1 Ms.

Commentaire de Benj1105 le 05/08/2003 14:38:37

En fait si j'ai bien compris ce que tu veux éviter c'est que plusieurs paquets soit envoyés comme n'étant qu'un seul ? (en une seule trame au lieu de trames séparées ?)

Commentaire de gabchampagne le 05/08/2003 14:58:08

oui. c quand tu veux faire un programme de chat et que les paquets risque de "fusioné".

Commentaire de LosAmigos le 06/08/2003 08:26:19

Moi, j'ai rajouté un caractère de fin qui me permet de séparer les paquets reçu
et donc, lors du getdata, je decoupe .

Commentaire de neria le 06/08/2003 08:36:34

Au lieu de mettre un Timer, essais de le faire attendre 1ms avec l'API sleep :

Declare Sub Sleep Lib "kernel32" ( ByVal dwMilliseconds As Long)

Commentaire de neria le 06/08/2003 08:38:14

Pour LosAmigos, ta technique est bonne, mais c'est embêtant quand tu fait un chat multiuser et qu'un utilisateur recoit une commande qui ne lui est pas destiné dans le paquet !!!, sinon ça fonction pour un chat simple !

Commentaire de Benj1105 le 06/08/2003 10:17:42

neria, concernant ton dernier message c'est impossible ! Tu as en effet forcement un socket par utilisateur, or chaque socket ayant son propre tunnel (ou flux) vers l'ordinateur client les packets ne peuvent pas se mélanger entre deux clients... (suis-je clair ? ^^)

Commentaire de neria le 06/08/2003 10:46:16

Non, tu as raison, j'ai confondu car j'ai trouvé aussi ce problème lorsque j'ai fait un chat entre 2 personne !

Commentaire de LosAmigos le 06/08/2003 12:22:44

merci benj, tu as tout a fait raison ;)

Commentaire de Benj1105 le 06/08/2003 13:18:57

Oui comme d'hab' lol :p
De plus je tiens à dire que c'est côté serveur que vous devez "refaire les messages", en effet si votre message est plus long que la fenêtre autorisée (paramètrable dans le registre sous windows (et accessoirement un autre parametre peut encore la diminuer dans le winsock)) il sera découpé... donc ton système ne permet pas de récuperer un message directement "correcte"
Voilà comment je fais: Dans mes messages je sépare chaque "paramètre" par un caractère (genre ¶) ce qui peut me donner par exemple:
say¶Benj¶Ce que je dis¶
(il faut mettre un ¶ à la fin pour le split ;)) puis à la toute fin du message je rajoute un autre caractère un spécial genre ¢ ce qui me donne au final pour mon message:
say¶Benj¶Ce que je dis¶¢

Bien, donc ca c'est pour l'envois, maintenant à la reception imaginons (même si c'est très peu probable à moins d'avoir une fenêtre ridiculement petite) que le message soit découpé ainsi:
say
¶Be
nj¶
Ce_
que
je_
dis
¶¢

Vous remarquerez qu'à chaque fois il envoit 3 caractères (c'est pour l'exemple hein :) comme vous l'aurez compris ce n'est pas une constante) J'ai matérialisé les espaces par des _  Et remarquez aussi que le dernier packet n'est composé que de deux caractères.
Alors la technique c'est qu'à chaque fois que je receptionne un packet je l'ajoute à une string.Ensuite on fait un split sur cette chaine avec le caractère de fin de message (¢ dans notre exemple) si le ubound est egal à 0 c'est qu'on a pas encore de message complet s'il est egal à 1 (ou plus) c'est bon, on a notre message. Ne reste plus qu'à l'analyser, pour ça je vous fait confiance quand même,mais surtout à le retirer de la chaine ce qui ne devrait pas vous poser de problème non plus, et puis réiterer le test à partir du split pour vérifier qu'on a pas un deuxième message (ce qui évite en plus de s'embarrasser avec la méthode que tu as donnée).

Voilà voilà j'espère que vous avez tout compris, sinon si vous voulez une p'tite source en VB6 ou .NET pas de problème :)

Commentaire de Benj1105 le 06/08/2003 13:31:10

Au début de mon "commentaire" précédent vous pouvez remplacer "serveur" par "côté reception" ;-) Je pense que ca avait besoin d'être clarifier car en fin de compte client et serveur sont des notions relativement abstraites puisque les deux côtés envoient et recoivent des données...

Commentaire de Greengold le 06/08/2003 13:59:41

Moi j'utilise la technique des entêtes de trames.
Par exemple, dans chacune de mes trames, les 3 premiers caractères sont un code que je récupère pour savoir de quel type de trame il s'agit.
Exemple : je veux envoyer un long message. Pour l'occasion ce sera : "0123456789". Disons que je limite la quantité de données envoyés à 4 octets (ou caractères).
"dtm0123"      -> début transfert message
"stm4567"      -> suite transfert message
"stm89"         -> suite transfert message
"ftm"             -> fin transfert message

Cette technique n'est valable que si l'on a un paramètre à faire passer. Pour plusieurs paramètres, disons que je veuille envoyer les préférences de mise en forme d'écriture de message d'un client. Je me fixe les règles suivantes : mon entête de trame sera "pmf", mon délimiteur (ou séparteur) de paramètres sera "|", mon 1er param sera la couleur de la police, mon 2eme param sera la taille de la police, mon 3eme param sera la font utilisée...

"pmf|bleu|14|arial"

Ensuite, le truc classique est de faire un selon (les 3 premiers caractères du winsock.getData) dans le dataArrival. Vive le Split... :)

Commentaire de docteurre le 14/08/2003 18:47:59

salut à tous
g regardé tout les posts et aucun ne me parait béton de chez béton pour eviter le mélange :
-les doevents ça marche un peu qd ça veut

-le coup du timer de 1ms et su sleep de 1ms aussi je trouve que c'est un peu au petit bonheur la chance genre peut etre que la trame aura le temps d'etre envoyée avant de se faire concatenée avec une autre, meme si le sleep de 1 est censé marcher. en plus si tu as besoin d'envoyer plusieurs packet rapidement tu perd 1ms par envoie au final ç peut faire beaucoup surtout si tu bosse en local

- la technique de Greengold pour les entetes de trame, ça bouffe de la bande passante et en plus tu sais jamais exactement à partir de combien la trame va etre découpé (winsock c'est parait-il 10 ko mais ça peut changer) donc tu peut pas choisir toi meme de la decouper à telle taille.

nan, moi je resterais sur la technique du split, mais j'ai pensé à une amélioration qui la blinderais :
le pb avec le split que par exemple si un chateur tappe ton caractère de fin et envoie le message, ton serveur va pas capter à koi correspont ce que le mec aura taper apres.... d'ou mon idée : mettre des caractères pour inhiber le ou les caractères de fin ;)

exemple :
caractère de fin : ;
inhibeur :

message = "salut moi je parle ds le chat; c'est bien "
message = inhib(message)
==> message est alors : "salut moi je parle ds le chat; c'est bien "
senddata "CHAT:" & message & ";"

ca vous parait comment ?

Commentaire de docteurre le 14/08/2003 18:50:34

salut à tous
g regardé tout les posts et aucun ne me parait béton de chez béton pour eviter le mélange :
-les doevents ça marche un peu qd ça veut

-le coup du timer de 1ms et su sleep de 1ms aussi je trouve que c'est un peu au petit bonheur la chance genre peut etre que la trame aura le temps d'etre envoyée avant de se faire concatenée avec une autre, meme si le sleep de 1 est censé marcher. en plus si tu as besoin d'envoyer plusieurs packet rapidement tu perd 1ms par envoie au final ç peut faire beaucoup surtout si tu bosse en local

- la technique de Greengold pour les entetes de trame, ça bouffe de la bande passante et en plus tu sais jamais exactement à partir de combien la trame va etre découpé (winsock c'est parait-il 10 ko mais ça peut changer) donc tu peut pas choisir toi meme de la decouper à telle taille.

nan, moi je resterais sur la technique du split, mais j'ai pensé à une amélioration qui la blinderais :
le pb avec le split que par exemple si un chateur tappe ton caractère de fin et envoie le message, ton serveur va pas capter à koi correspont ce que le mec aura taper apres.... d'ou mon idée : mettre des caractères pour inhiber le ou les caractères de fin ;)

exemple :
caractère de fin : ;
inhibeur :

message = "salut moi je parle ds le chat; c'est bien "
message = inhib(message)
==> message est alors : "salut moi je parle ds le chat; c'est bien "
senddata "CHAT:" & message & ";"

ca vous parait comment ?

Commentaire de Greengold le 14/08/2003 19:39:16

En réponse au commentaire de docteurre :

*** Utiliser des en-tetes de trames bouffe de la bande passante :

Mes en-tetes sont définies sur 3 octets --> OULALA, 3 octets dans une trame, mais ça noie absolument toute la bande passante, avec cette méthode, il faut une connexion adsl 1024 ou T1 sinon c pas la peine...

*** tu peut pas choisir toi meme de la decouper à telle taille :

Eh ben si ! je le peux, si tu veux pas être enmerdé tu limites tes trames à 6 Ko et puis voilà. Il faut savoir que dans un logiciel comme un chat, les plus gros transferts sont les messages, mais dans tous les chats que j'ai utilisé, toutes les zones de texte d'écriture des messages sont limitées en cararctères, donc pas de soucis de dépassement de capacité de la trame à envoyer.

*** le pb avec le split que par exemple si un chateur tappe ton caractère de fin :

Le ";" je l'utilise pour les messages systèmes (internes à mon appli) donc pas de pb. Si tu regardes la première partie de mon explication, tu verras que je n'utilise pas de délimiteur... Ta solution de mettre le délimiteur à la fin n'a aucun sens... C'est à se demander si tu t'es déjà servi du split et si tu as compris le principe de traitement des trames coté serveur...

*** si tu as besoin d'envoyer plusieurs packet rapidement tu perd 1ms par envoie au final ç peut faire beaucoup surtout si tu bosse en local :

OULALA, mon Dieu !! Une milli seconde, mais c énorme !!! Pour ta gouverne, si on se base sur la théorie, en une seconde, j'envois 1000 trames... T'as encore dis une connerie mon pauvre... Avec cette méthode pour l'envoi d'un fichier de 1 Mo (timer à 1 Ms + trames à 6 Ko, en comptant aussi la mise en mémoire du fichier et la reconstruction du fichier...), ça prend qq secondes à être transféré...

*** le coup du timer de 1ms et su sleep de 1ms aussi je trouve que c'est un peu au petit bonheur la chance :

Notre pb est le suivant : si on envoit plusieurs trames au meme socket, sur de l'execution machine, les trames se concatènent. Normal, puisque un processeur de 1 GHz par exemple, exécute 1 MIPS (million d'instructions "machine" par seconde), ce qui équivaudrait (au pif) à un timer à 1/100000 seconde... Nous, on utilise pour résoudre ce pb, un timer à 1/1000 seconde, c qui passe super largement... Décidément, t'as rien testé avant de dire toutes tes âneries...


Alors la prochaine fois avant de te lancer dans un commentaire non constructif et avant de critiquer tout le monde, tu ferais mieux de faire des tests. Je ne supportent absolument pas les mecs qui critiquent alors qu'ils n'y comprennent pas grand choses eux mêmes, voire rien du tout dans ton cas. Moi, avant de mettre mon commentaire sur cette source, j'ai suivi des cours sur les winsocks, j'ai fait une bataille navalle en réseau, un chat poste à poste et une appli (client et serveur) qui simule le principe d'un ftp avec transfert de fichiers sur un réseau.
A bon attendeur...

Commentaire de docteurre le 14/08/2003 23:12:52

oula oula calmos j'ai jamais voulu etre méchant ni quoi que se soit calme toi... toutes les methodes ici se valent et fonctionnent bien, seulement chacune à ses avantage et ces defaut, je me contentais uniquement de les énumérer sans arrière pensée... t'énerve pas ;)

en plus de ca je ne crois pas avoir fais un commentaire non contructif étant donné que j'ai essayé d'aporter une amélioration à une technique , en l'occurence celle de Benj1105 (et pas la tienne en plus, mais ça reste du split). alors si t'accepte pas qu'on puisse critiquer (en bien et en mal) tes methodes, c'est pas de ma faute, même si je m'y suis peut etre mal pris dans mon language. désolé mais je vais pas non plus me prendre le choux et etre super poli dans un forum, on est là pour s'entraider pas pour se faire des courbettes...

bon mis à par ça :
pour les timer : utiliser les timer ou les sleep alors que l'ont peut faire autrement je trouve ça porc personnelement après chacun pense ce qu'il veut

pour l'histoire du split et caractère de fin : ce que je voulais dire, c'est pour ton exemple, si un chateur tape "blablaftmdtmblabla" dans sa fenetre, avec ta technique, ca devrait (je pense) faire 2 messages distinct (2 fois blabla); je veut bien que ça soit très rare mais bon dis moi si j'ai tord. d'ou mon idée de mettre un seul caratère entre 2 messages et de l'inhiber par un autre caratère dans le cas ou l'utilisateur le rentre dans la fenetre de chat

*** tu peut pas choisir toi meme de la decouper à telle taille :
j'ai lu sur un site que un utilisateur peut choisir la taille maxiamle de ses trames sous windows, donc j'ai pas vérifié mais c t uniquement pour cela que je disait ca ; si winsock sépare ses paquets automatiquement, ca doit etre fais pour donc mieux vaut le laisser faire et utiliser une autre technique.

<<  tu verras que je n'utilise pas de délimiteur... Ta solution de mettre le délimiteur à la fin n'a aucun sens >> toit tu met tes "délimiteurs" au début sous la forme dtm stm ftm, ca reviens au meme que moi en mettant un ";" à la fin nan ?

aller a+ et reste zen

Commentaire de Greengold le 14/08/2003 23:52:09

Bon en fait j'ai relu ton post et c vrai que je me suis un peu amballé :) Mais bon, toi de ton coté tu n'as pas été suffisament rigoureux.

plusieurs personnes on proposé des solutions techniques, et toi qd tu parles d'une technique tu ne dis pas à qui elle appartient... ça va pas.

*** le coup du timer de 1ms et su sleep de 1ms aussi je trouve que c'est un peu au petit bonheur la chance genre peut etre que la trame aura le temps d'etre envoyée avant de se faire concatenée avec une autre.

Si tu trouves qu'il y a une meilleure solution, expose là direct, en plus tu sais que ça marche et tu dis "au petit bonheur la chance", non là, ça passe pas, tu peux dire que c pas optimisé ou ce que tu veux mais pas un tel commentaire.

*** la technique de Greengold pour les entetes de trame, ça bouffe de la bande passante.

Là c du foutage de gueulle qd meme, admet-le, meme sur un 56K, ça n'a aucune incidence... et encore moins sur réseau local qui est à 100 Mbits...

Pour l'histoire de la séparation des paquets... moi j'ai trouvé que les trames winsoks sont limitées à environ 8 Ko. Donc on peut parfaitement définir une limite < à 8 Ko. Au-delà, le paquet est envoyé en plusieurs fois.

Et Pour finir, pour l'histoire du split et caractère de fin : t'as pas fais gaffe que sur le data arrival coté serveur, j'analyse mes en-tetes de trames (différents de délimiteur !!) , c-a-d, les 3 premiers caractères, donc ton exemple : "blablaftmdtmblabla", coté client je fais un senddata de "DTM" & "blablaftmdtmblabla", puis un senddata de "FTM". Pour moi c la solution ultime. Impossible qu'il y ait une erreur. Relie bien mon exemple, je définie des trames à taille personnalisée, et je gére le dépassement de la limite de capacité des trames avec mes en-tetes. Voilà !

Donc, si tu veux faire de la critique de sources, il va falloir être plus rigoureux... et par exemple faire des test avant de trop s'avancer.
Enfin, quoi qu'il en soit, j'ai absolument rien contre toi, malgré les apparences (trompeuses), sans rancune ?

Commentaire de docteurre le 15/08/2003 00:15:01

je suis tout à fais d'accord avec ton l'ensemble de ton dernier post (sans rancune aucune ;) )

sinon, ta technique est ok, théoriquement elle est sencé fonctionner impec, mais je pense qu'avec la mienne on peut éviter le découpage des trames par nous et laisser ce travail à winsock

ce que je fais exactement coté serveur :
j'ai une chaine de char ; lors d'un dataarrival, je met tout ce que je recois ds la chaine
ensuite je la parse : si je trouve des ";" qui ne sont pas précédés par un "", je selectionne la partie de la chaine située entre cet ";" et le ";" précédant ou le début de ma chaine; j'envoie alors ce fragment de chaine a une fonction qui se chargera de faire le boulot avec une trame nickel. ensuite je vide ma chaine et si il y restait des éléments restant après le dernier ";", je les remet dans ma chaine. comme ça ils seront traités la fois d'après dans le cas ou la trame est découpée par winsock.

coté client je peut donc me permettre d'envoiyer mes trames ainsi : senddata trame1 & ";" & trame2
sans me poser de question et je saurais que les trames seront redécoupés à l'arrivée; si une tramer contient ";", il suffit de mettre le caractère inhibeur devant (";") et ainsi il se sera pas pris en compte lors du découpage des trames coté serveur.

voilou a+

Commentaire de docteurre le 15/08/2003 00:17:20

désolé mais mon caratère inhibeur n'a pas l'air de passer dans le forum, c'est un backslash, fo le mettre devant le ";" pour quil ne soit pas pris en compte lors du découpage

Commentaire de Benj1105 le 15/08/2003 13:17:03

Beuh... Je vois aps ce que vous y reprochez à mon système.... Il a l'avantage de faire des paquets simples à interpreterDe plus j'empêche  les gens d'envoyer mon caractère de séparation tout simplement.... Puis aussi bien je me fous d'envoyer 4/5 octets supplémentaires vu que 1) Même pour un 56K c'est pas énorme et 2) Mon logiciel est plutôt pour des connexions ADSL donc...

Commentaire de docteurre le 15/08/2003 13:50:27

wai mais si tu envoie un fichier tu peut pas te permettre d'empecher l'envoi de ton caractère sil est contenu ds le fichier...

j'ai pensé à une autre technique


tu envoie en entete la taille de la trame

genre 10:CHAT:salut8OPENCHAT

comme ça il te suffit de découper à chaque fois du nombre de caractère suivants et tu retombera pile au début de la trame suivante donc ça devrait aller... je teste ça.... sinon pour mon ancienne technique mis à part que le parsging (parcours) de la chaine coté server et la suppression des inhibiteur soit lourde, ya un autre problème: CHAT:\\\\; ==> ce message inihibe mon caractère de fin... en fait le dernier caratère du message ne dois pas etre un  sinon ça marche po...

donc je teste la nouvelle technique qui me semble encore mieux

Commentaire de Benj1105 le 15/08/2003 16:32:06

Si je transfert un fichier j'ouvre un second socket moi.... (avec une méthode un peu spéciale....)

Commentaire de docteurre le 15/08/2003 19:25:18

aaaa mais c mal ca ;) fo essayer de le faire avec un seul si possible et ça l'est forcement vu que les softs pro et meme d'autres le font ;)

Commentaire de Benj1105 le 17/08/2003 14:30:16

C'est forcement quoi ? ^^
Je vois pas en quoi c'est mal... au contraire !

Déjà le fait de changer de socket permet de changer le port d'écoute... ce qui permet entre autre d'avior une meilleure sécurisation... Puis bon, ouvrir un socket ne présente pas de grande difficulté en .NET ^^ (oui l' API de .NET est plutôt pas mal niveau socket, mais elle bugge concernant le contrôle winsock par contre ! :-/)

Vilà vilà...
Mais sinon y a encore mieux si tu veux pas ouvrir de deuxième socket... tu rajoute un seul octet pour indiquer l'opération en cours, par exemple, admettons que tu fais un truc de chat où tu peux aussi envoyer des fichiers, tu fais que tu on premier caractère correspond  à l'action en cours, c'est à dire, par exemple si je parle le premier caractère serait ! ce qui pourrait donner:

!Ce que je dis

Et par exemple pour un chuchot, (il faut donc un parametre supplémentaire) le 1er serait ? et pour trouver la longueur tu pseudo du destinataire tu code en hexadécimal... (beaucoup mieux ! :))


De toutes façons y a plusieurs méthodes correctes

@++

Commentaire de sub-zero le 14/09/2003 21:15:29

la solution réside dans la modification directe des propriétés du handle du socket ;)

personnellement j utilise l API  setsockopt pour désactiver l optimisation nodelay du protocole TCP (algo de nagel), j active le linger et j augmente la taille du tampon en envoi et réception.

couplé à une solution de splitage des paquets par caractère ésparateur, les résultats sont concluant.

Commentaire de kimmelf2 le 24/09/2003 01:28:53

hey !

j'ai juste une petite question dans un autre domaine : comment vous faites pour "rediriger" (j'entend par la changer de port) une connexion lors de winsock_connectionrequest ???

car un nouvel intervenant sur un chat doit se voire attribuer un socket sur un port libre sur la machine distante (du moins je pense) hors il ne peux pas determiner celui ci de lui meme, c'est uniquement la machine distante qui peux l'attribuer.

moi j'avais fais un "protocole" barbare :
notations :
machine A : machine deja connectee
machine B : nouvel intervenant
IPA = Ip de la machine A
IPB = IP de la machine B
psA = port "serveur" de la machine A
p1A = un port sur la machine A
p2A = un autre port de la machine A
...
psB, p1B, p2B ... idem mais sur la machine B

sur psA et psB, un socket en ecoute permanante (d'ou le terme "port serveur")
A a deja 3 connexion : p1A, p2A, p3A

B determine un port libre : p1B
B, depuis p1B, se connecte a IPA sur le port psA
A recupere l'IPB et p1B, se deconnecte sur psA et se remet en ecoute
A determine un port libre : p4A
A, depuis p4A, se connecte a IPB sur le port p1B

complique .....

vos avis ?? des suggestions ?? merci d'avance

Commentaire de docteurre le 24/09/2003 08:43:03

j'ai vite fais ragardé mais regarde ds l'aide de msdn comment ils font pour faire de la multi-connexion en TCP (avec des groupes de controles) peut etre que ça t'aidera, je regarderais ton post plus en detail un peu plus tard ;)

Commentaire de Benj1105 le 24/09/2003 17:38:41

En fait pas besoin d'utiliser un port different à chaque connexion ! Un port ne peut être qu'une fois en listening mais pas en communication !

Commentaire de kimmelf2 le 25/09/2003 02:05:25

je resume en + claire (du moins j'esperes)

B veut chatter avec A qui est deja connecte

- B se connecte sur un port fixe predefini (le port serveur) de A (ce port est en ecoute)
- le socket sur le psA recupere l'IP et le port de B puis se remet en ecoute pour choper de nouveaux arrivants
- A etabli une connexion depuis un de ses ports libre (p4A) vers l'IP et le port de B qui ont ete recuperes

En fait, B se presente a A par une connexion sur psA
Puis A cree la connexion qui sera vraiment utilisee pour chatter

en schema :

Cote A                        Cote B
(IPA, psA)   <----------- (IPB, p1B)  Connection etablie par B

A recupere IPB et p1B, puis remet psA en ecoute
A determine p4A

(IPA, p4A)   -----------> (IPB, p1B) Connection etablie par A



c'est un peu tire par les cheveux !!!


sinon, autre methode :
B se connecte a A sur psA
A determine un port libre (p6A) et envoi p6A a B
B se deconnecte de psA
B se reconnecte a A sur p6A

Commentaire de sub-zero le 25/09/2003 10:16:07

personnellement j'utilise uniquement des classes (ajouter winsock.ocx comme référence et non comme composant) ce qui permet d instancier les object du genre dim mysock as new winsock


pour gérer ton pb, tu crée un objet winsock ds ta classe
private withevents sock as new winsock

exemple d un serveur d authentification
....
m_type = srvIdent
sock.close
sock.Bind port, ip (on peur binder l IP de son choix en case de plusieurs IP)
sock.Listen
...


et tu passes le request ID a la classe qui va gérer ca.( ici c un exemple d un serveur multi tache)

Private Sub sock_ConnectionRequest(ByVal requestID As Long)
'***Procédure de traitement des requetes de connexion****
Dim t As Object
If mycol.Count < Maxclients Then
nb = nb + 1
   Select Case m_type
    '//serveur d identification
    Case srvIdent:
    Set t = New CServeurLogin
    mycol.Add t, Hex(t.ServeurIDent)
    t.AffectSocket requestID, Me, timeout, m_msgA, m_filtre
    
    '//serveur de messagerie
    Case srvChat:
    
    '//serveur de recherche
    Case srvFinder:
    
    '//serveur de fichiers
    Case srvBrowser:
    Set t = New CServeurBrowser
    mycol.Add t, Hex(t.ServeurIDent)
    t.AffectSocket requestID, Me, timeout
    End Select
End If
Set t = Nothing
End Sub

et dans la classe CserveurLogin
un autre object withevents sock

Public Sub AffectSocket(sID As Long, srv As CServeur, Optional sTimeOut As Long = 4000, Optional msg As String, Optional filtreparts As Boolean = True)
Dim flag As Boolean
If sock.State <> sckClosed Then sock.Close
sock.Accept sID
....
end sub



un port a l'écoute peut accepter un nbre presque illimité de clients à condition d opter pour un système multithreads. La destruction de la collection ou de l objet via la classe principal impose la fermeture du port.

j obtiens des performences très intéressantes avec ce procédé.

Commentaire de kimmelf2 le 26/09/2003 00:13:52

pour resumer (le principe de base) :
tu fais un truc du genre

sck1 et sck 2 = controles winsock

sck1.listen

sub sck1_connectionrequest(byval id as long)
sck2.accept id
end sub

c'est sck1 qui recoi la demande de connection mais c'est sck2 qui l'accepte

et dans ton exemple, tu utilise une collection de winsock plutot qu'un nombre predefini (ca je le savais)

la ou je bloquais, c'est que je croyais que c'etais le winsock qui recevais le connectionrequest qui devais accepter l'IDRequest

mais si je peux l'accepter par un autre winsock ... ca deviens beaucoup + simple !

Commentaire de tbbuim1 le 29/03/2005 15:31:50

Ca aurait été super top over méga génial avec une petite source de rien du tout pour faire un tout petit exemple...
Ca à l'air pas mal, mais ça manque de commentaires explicatif, de ce fait, je n'arrive pas à m'en servir.
Quand doit on se servir de la fonction vider_Pile?
Qd je fais Pile.Add "données" à la place de SendData, il y a une erreur qui me dit Object Required...
Quand tu dis, éviter que les paquets se mélangent, ça veut dire quoi? Parce que moi les paquets se concatènent si je les envoi à la suite, et j'aimerais qu'ils me les envoi un par un, est-ce ta source sert à faire ça? Merci répondre.

Commentaire de tbbuim1 le 29/03/2005 16:03:08

Bref, quelqu'un aurait-il une solution claire, nette et précise qui fonctionne?

Commentaire de tbbuim1 le 31/03/2005 15:51:22

Ok j'ai capté comment l'utiliser, mais ça marche pas top :(
J'ai des messages qui se concatènes qd mm mais pas systématiquement :( Donc ce n'est pas une solution fiable.
C'est qd mm incroyable qu'il n'y ait pas de moyen de faire ça sans renvoyé un message du serveur!

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,686 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales