[..] Grandes données TCP

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

[..] Grandes données TCP

#1

Message par Tetdoss »

Salut à tous, j'ai essayé de créer 2 fonctions : send_data et recv_data pour recevoir et envoyer des données avec le protocole TCP.

Voici ma fonction send_data

Code : Tout sélectionner

Func send_data($socket, $data)
    
    $data = Chr(2) & $data & Chr(3)
    $data = _Crypt_EncryptData($data, $CALG_3DES, "Tetdoss")
    Return TCPSend($socket, $data)
    
EndFunc
J'ai "encadré" ma donnée avec Chr(2) et Chr(3)

Je voudrais pouvoir récupérer à l'octet près, cette donnée, sachant chaque "bout" (packet) de donnée reçue fait 2048 octets...

Voilà je sais pas trop si c'est faisable mais ça me permettra de gérer l'envoie de n'importe quel fichier, même ceux supérieur à 2048 octets !

En espérant m'avoir fait comprendre, merci d'avance !
Tetdoss
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#2

Message par Tetdoss »

Bon j'ai réfléchi et j'ai pensé à une autre méthode, mettre dans l'en-tête d'un paquet la taille de la donnée. Mais il faudrait que cet en-tête ait toujours la même taille... Je pense que c'est la meilleure des solutions.
Je vais essayer de réfléchir là-dessus en attendant.

Je pense à quelque chose de ce genre :

Code : Tout sélectionner

Func send_data($socket, $data)
    
    $data = _Crypt_EncryptData($data, $CALG_3DES, "Tetdoss")
    $len = BinaryLen($data)
    $data = $len & $data
    Return TCPSend($socket, $data)
    
EndFunc

Func recv_data($socket)
    
    $len = TCPRecv($socket, 8)
    $data = TCPRecv($socket, $len)
    $data = _Crypt_DecryptData($data, $CALG_3DES, "Tetdoss")
    
    Return $data
    
EndFunc
Mais comment puis-je être sûr que $len est de 8 octets... J'ai fait des tests et en fonction du nombre, c'est 4 ou 8 ^^
Tetdoss
Avatar du membre
Iste
Niveau 11
Niveau 11
Messages : 1870
Enregistré le : jeu. 04 déc. 2008 14:21
Localisation : 76
Status : Hors ligne

Re: [..] Grandes données TCP

#3

Message par Iste »

attendez, je ne suis aps sur de comprendre.

les fonctions TCP d'AutoIt font déja tout le boulot
Vous n'avez pas a vous préoccuper des entête et des paquet.

Pouvez vous nous donner un cas concret de votre probleme, si possible dans un mini projet de test préconstruit ?
Signez ici
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#4

Message par Tetdoss »

Salut merci de ta réponse Iste, en fait je voudrais faire un code sans me soucier du paramètre $maxlen de TCPRecv, je voudrais obtenir à chaque fois, toute la donnée $data, qu'elle soit grosse ou non.
Tetdoss
Avatar du membre
Iste
Niveau 11
Niveau 11
Messages : 1870
Enregistré le : jeu. 04 déc. 2008 14:21
Localisation : 76
Status : Hors ligne

Re: [..] Grandes données TCP

#5

Message par Iste »

Votre connexion est ponctuelle (ouverture, envoi, fermeture) ou continue ?
Dans le 1er cas, inspirez vous simplement de l'exemple de la doc ou de ceux du forum.
$maxlen ne dit pas "attention, tu vas recevoir xxx byte" mais "bon, envoi les xxx prochain byte"
on procède ainsi, car il est rare que tout les byte soient arrivés lors du traitement.

Du coup, il nous faut juste une boucle, qui va faire des TCPRecv() de quelque caractères (a vous de voir combien, 4000semble cool) et les ajouter a un buffer. Des que TCPRecv() renvoi une erreur, c'est qu'on en a fini, notre buffer contient notre info.

Pour le cas d'une connexion continue, ca sera un peu plus complexe, mais dans la meme idée.
Signez ici
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#6

Message par Tetdoss »

Ahah :) ça m'a l'air pas mal comme ça !

Biensûr ma connexion est ponctuelle, j'avais complètement oublié la return value de TCPRecv, en fait la maxlen c'est juste la taille d'un bout de la donnée.

Je crois avoir compris, j'essaie et je vous tiens au courant :) .

PS : C'est la première fois que je me mets aux réseaux alors j'ai un peu de mal ^^
Et c'est cool que TCP gère les en-têtes !
Tetdoss
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#7

Message par Tetdoss »

Voilà j'ai fait quelque chose comme ça :

Code : Tout sélectionner

Func send_data($socket, $data)
    
    $data = _Crypt_EncryptData($data, $CALG_3DES, "Tetdoss")
    Return TCPSend($socket, $data)
    
EndFunc

Func recv_data($socket)
    
    While 1
        If ($data = TCPRecv($socket, 2048)) Then
            $buffer = $buffer & $data
        Else
            ExitLoop
        EndIf
    WEnd
    
    $buffer = _Crypt_DecryptData($buffer, $CALG_3DES, "Tetdoss")
    
    Return $buffer
    
EndFunc
Je n'ai pas encore l'occasion de tester ce code mais quand je le ferai, je passerai ce sujet résolu (si ça marche biensûr)
Tetdoss
Avatar du membre
matwachich
Membre émérite
Membre émérite
Messages : 986
Enregistré le : lun. 19 oct. 2009 04:04
Localisation : Algérie
Status : Hors ligne

Re: [..] Grandes données TCP

#8

Message par matwachich »

Juste au cas ou, j'ai fait exactement la même chose dans mon UDF, vous pouvez envoyer n'importe quelle fichier, données binaire, ou chaîne de caractère!
D'ailleur, le Chr(2) --- Chr(3) me dis quelque chose... :P

Pour répondre à votre question, regardez la fonction __TCPServer_SocketCheckBuffer dans le fichier TCPServer.au3
Sortons VW du coté obscure! - La curiosité est un vilain défaut! Cliquez ici
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#9

Message par Tetdoss »

Merci beaucoup pour ton UDF, j'ai bien étudié ton UDF en OO et l'autre.

J'ai choisi celui que tu viens de me montrer, car je n'aime pas mélanger de la POO avec de la programmation sans objets :) . De toute façon, même celui que tu viens de me passer ressemble à de la POO avec toutes ces variables globales :) .

Enfin bref, j'ai pris du temps à comprendre comment il fonctionnait et je crois que je suis parti là , je verrais juste comment faire pour envoyer des données contenant plusieurs "sections"
Tetdoss
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#10

Message par Tetdoss »

J'ai un problème dans ton UDF :
E:\Documents\Programmation\AutoIt\SDK\AutoIt3\Include\SimpleTCP\TCPServer.au3 (530) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
$ret[$ret[0] + 1][0] = $__TCPServer_Sockets[$i][0]
$ret[^ ERROR
>Exit code: 1 Time: 7.915
Le problème vient de cette fonction :

Code : Tout sélectionner

Func _TCPServer_SocketList()
    If Not _TCPServer_IsStarted() Then Return SetError(-1, 0, 0)
    ; ---
    Local $ret[1][2] = [[0,""]]
    ; ---
    For $i = 1 To $__TCPServer_Sockets[0][0]
        If $__TCPServer_Sockets[$i][0] <> -1 Then
            ReDim $ret[$ret[0][0] + 2][2]
            $ret[$ret[0] + 1][0] = $__TCPServer_Sockets[$i][0]
            $ret[$ret[0] + 1][1] = $__TCPServer_Sockets[$i][1]
            $ret[0][0] += 1
        EndIf
    Next
    ; ---
    Return $ret
EndFunc
Edit : il manque 2 [0] dans cette fonction je crois, ce n'est pas $ret[0] mais $ret[0][0]
Tetdoss
Avatar du membre
matwachich
Membre émérite
Membre émérite
Messages : 986
Enregistré le : lun. 19 oct. 2009 04:04
Localisation : Algérie
Status : Hors ligne

Re: [..] Grandes données TCP

#11

Message par matwachich »

En effet, merci de retour!
La fonction correct est:

Code : Tout sélectionner

Func _TCPServer_SocketList()
    If Not _TCPServer_IsStarted() Then Return SetError(-1, 0, 0)
    ; ---
    Local $ret[1][2] = [[0,""]]
    ; ---
    For $i = 1 To $__TCPServer_Sockets[0][0]
        If $__TCPServer_Sockets[$i][0] <> -1 Then
            ReDim $ret[$ret[0][0] + 2][2]
            $ret[$ret[0][0] + 1][0] = $__TCPServer_Sockets[$i][0]
            $ret[$ret[0][0] + 1][1] = $__TCPServer_Sockets[$i][1]
            $ret[0][0] += 1
        EndIf
    Next
    ; ---
    Return $ret
EndFunc
Je met à jour le Sujet d'origine.
Sortons VW du coté obscure! - La curiosité est un vilain défaut! Cliquez ici
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#12

Message par Tetdoss »

J'avance j'avance :) J'ai trouvé une autre erreur je crois bien.

Lors de du Func _TCPServer_Process(), tu fais des Call en envoyant $i en 2ème paramètre :

Call($__TCPSrv_Info_CB_LOST, $i, $__TCPServer_Sockets[$i][1])

Or c'est plutôt $__TCPServer_Sockets[$i][0] qui nous intéresse, car c'est la VRAIE ID du client. Ton exemple est alors faut car tu fais dans Func _TCP_Recv($iSocket, $sIP, $Data) :

Local $nick = _TCPServer_ClientPropertyGet($iSocket, 0)

Mais je peux me tromper car ce n'est pas mon UDF.

PS : Ce que j'appelle VRAIE ID, c'est par exemple 689 ou 742. En passant, cette ID peut-elle être égale à 0 ? Car j'initialise $client_id (ma variable contenant le client principal de mon prog) à 0 :) j'ai trouvé, la VRAIE ID c'est le retour de TCPListen :) et donc je crois bien que tu t'es trompé.

Ma correction :
► Afficher le texte
Tetdoss
Avatar du membre
matwachich
Membre émérite
Membre émérite
Messages : 986
Enregistré le : lun. 19 oct. 2009 04:04
Localisation : Algérie
Status : Hors ligne

Re: [..] Grandes données TCP

#13

Message par matwachich »

Noooooooooooooooon attention!!!!
Le SocketID de mon UDF n'a RIEN à voir avec le hSocket des fonctions TCP d'AutoIt!

Au début, c'était comme cela, après je me suis rendu compte que c'est bien mieux ainsi, en terme de performances et de simplicité de gestion.

Alors SVP, ne touchez pas à ça!!! :evil: :P

PS: d'ailleur, pour s'en rendre compte, il n'y a qu'à remarquer l'existance des fonctions: _TCPServer_SocketID2SocketHandle et _TCPServer_SocketHandle2SocketID
Sortons VW du coté obscure! - La curiosité est un vilain défaut! Cliquez ici
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#14

Message par Tetdoss »

Bah alors le socket ID que je prends avec le socket list n'est pas bon ?? Car moi j'ai l'ID de retour de TCPListen à chaque fois.

PS : voir au-dessus pour socket list
Tetdoss
Avatar du membre
matwachich
Membre émérite
Membre émérite
Messages : 986
Enregistré le : lun. 19 oct. 2009 04:04
Localisation : Algérie
Status : Hors ligne

Re: [..] Grandes données TCP

#15

Message par matwachich »

Aie! :oops: J'me suis fait prendre en flagrant délit de non concentration!!!
Et une nouvelle version! Correction dans le post d'origine de SimpleTCP
► Afficher le texteFonction _TCPServer_SocketList Corrigée
Un grand merci à vous!!!

Edit: Le SocketID de mon UDF commence à 1, pas à 0. Et n'utilisez pas de array contenant tous vos clients, utilisez plutôt les fonctionalitées de _TCPServer_ClientsPropertyXXX, elle servent justement à ça, ne pas avoir à gérer de array soit même.
Modifié en dernier par matwachich le lun. 21 nov. 2011 22:13, modifié 1 fois.
Sortons VW du coté obscure! - La curiosité est un vilain défaut! Cliquez ici
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#16

Message par Tetdoss »

Ce n'est rien, je voyais bien qu'il y avait un mélange d'ID bizarre ^^ je vais tester ça.

EDIT : c'est beaucoup mieux maintenant :)
Tetdoss
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#17

Message par Tetdoss »

utilisez plutôt les fonctionalitées de _TCPServer_ClientsPropertyXXX
En fait je visualise tous mes clients dans une view list pour en choisir un seul donc pas besoin ^^

Image
Tetdoss
Avatar du membre
Tetdoss
Niveau 3
Niveau 3
Messages : 39
Enregistré le : mar. 15 nov. 2011 23:23
Localisation : France 76
Status : Hors ligne

Re: [..] Grandes données TCP

#18

Message par Tetdoss »

J'ai une question, je voudrais envoyer des données avec un séparateur par exemple "|". Le problème, c'est que je n'arrive pas à gérer le cas ou l'utilisateur décide d'envoyer une chaîne avec ce caractère, j'ai pensé à un StringReplace($data, "|", "||") mais ensuite, je voudrais récupérer toutes les chaînes entre 2 "|" mais StringSplit ne fonctionne pas ici, car il va prendre en compte les "||". Dois-je faire mon algorithme tout seul ou existe-t-il une fonction ? Ou alors avez-vous un algo à me proposer ?
C'est un truc à rajouter dans ton UDF matwachich :)

Merci.
Tetdoss
Avatar du membre
matwachich
Membre émérite
Membre émérite
Messages : 986
Enregistré le : lun. 19 oct. 2009 04:04
Localisation : Algérie
Status : Hors ligne

Re: [..] Grandes données TCP

#19

Message par matwachich »

Quand je veut faire ça, je sépare mes données par Chr(11).
Je l'utilise par exemple pour envoyer des fichiers, tout simplement! (plus simple, tu meurs!)

Envoyeur:

Code : Tout sélectionner

; ouvrir un fichier en mode binaire
$hFile = FileOpen("fichier", 16)
; lire le contenu
$data = FileRead($hFile)
FileClose($hFile)

; ensuite, on envoi tout simplement. (le file servira juste à dire que c'est un fichier)
_TCPServer_Send($iSocket, "file" & Chr(11) & $data)
 
En suite, le receveur:

Code : Tout sélectionner

; La fonction callback de reception
Func _TCP_Recv($iClient, $Data)
    ; vérifier si c'est un fichier
    If StringLeft($Data, 5) = "file" & Chr(11) Then
        $Data = StringSplit($Data, Chr(11))
        ; ouvrir un fichier en mode écriture binaire
        $hFile = FileOpen("fichier", 18)
        FileWrite($hFile, $Data[2])
        FileClose($hFile)
        Return
    EndIf
    ; ---
    ; Sinon, si c'est pas un fichier, bah la c'est votre problème!
EndFunc
 
PS: à propos de StringSplit, lisez bien la doc, vous verrez qu'elle peut très bien diviser par "||" sans retourner le vide entre les 2 |, voyez le flag (dernier paramètre)
Sortons VW du coté obscure! - La curiosité est un vilain défaut! Cliquez ici
Avatar du membre
matwachich
Membre émérite
Membre émérite
Messages : 986
Enregistré le : lun. 19 oct. 2009 04:04
Localisation : Algérie
Status : Hors ligne

Re: [..] Grandes données TCP

#20

Message par matwachich »

C'est un truc à rajouter dans ton UDF matwachich
Cadeau!
Sortons VW du coté obscure! - La curiosité est un vilain défaut! Cliquez ici
Répondre