Remplacer ReceiveNetworkFile

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Remplacer ReceiveNetworkFile

Message par Kwai chang caine »

Bonjour à tous

Bon j'ai presque fini, mon transfert de fichier par FTP :D

Mais j'ai un tout petit détail qui me chagrine :roll:
Ooooh un pas grand chose, presque rien .....

Grace à votre aide et celle du US :

1/ Je suis arrivé a faire un anneau
2/ A incorporer dans cet anneau une spirale crée par TYPHOON
3/ A changer cette spirale pour la remplacer par celle du SOLDAT (A cause de l'histoire que celle de typhoon ne marchait qu'en 4.40 pour le carré rouge)
4/ A remplacer le carré rouge par l'icone du fichier droppé
5/ A rajouter des effets sonores du plus grand chic et qui collent super bien au programme

Il me reste donc un detail, trouver comment cacher un icone sur le bureau ou le deplacer avant qu'il n'y arrive, et tout est fini :D
Je suis donc super content, mais comme je vous disait, reste ce petit grain de sable.....

Mon transfert FTP ne marche plus
Image

J'ai lu par ci par la que la fonction ReceiveNetworkFile n'etait pas fiable, et en plus on a pas la main dessus, pour les ProgressBar par exemple.
J'ai meme lu que FRED voulait passé un temps la supprimer 8O

Qu'il fallait la remplacer par ReceiveNetworkData.......

Bon tres bien...KCC il est pas borné (ou presque :oops:), il a donc essayé plusieurs codes et aucun ne marchent vraiment à fond, a commencer par le miens.
Pour le miens apparement j'avais fait tout simple comme y dit FRED, mais doit manquer des timing, car FRED y dit que quand le retour est plus petit que le buffer, c'est que c'est fini.
En fait pas du tout, moi, de temps en temps le retour est plus petit que le buffer et je ne savais pas pourquoi ??? 8O

Le probleme c'est souvent quand on refuse le telechargement, ça coince je ne sais pas quoi dans le buffer de FRED, et la deuxieme fois que l'on envoi....y'a "beugue" :?

Alors j'ai essayé des codes de fous, avec des tempos de partout sur le fofo anglais, puis un autre et y'a toujours un "miasme queque part" :?

Celui la c'est un code de dingue...et y'a tellement d'underscore qu'on dirait qu'il est ecris à la main :(
http://www.purebasic.fr/english/viewtop ... 87#p261687

Celui la, c'est celui que je torture avec un chausse pied depuis deux jour pour qui rentre dans mon anneau
Mais y'a au final le probleme du refus de transfert, en plus c'est pas les underscores qui pululent....mais les timers et les conditions dans celui ci :(
http://www.purebasic.fr/english/viewtop ... 62#p157362

J'suis meme allé voir sur code archive avant de vous deranger, et sur le forum allemand....mais pas facile de trouver :(
Y'a beaucoup de FTP avec "la terre nette"..mais moi c'est en local que j'ai besoin :roll:

Donc bref....je voulais savoir si l'un de vous avait vu un code de transfert de fichier, qui marche dans tous les cas ????
Bon pas trop compliqué.....car c'est pour KCC :oops:

Voila voila.....autrement KCC y va etre obligé de ranger son code dans la spirale qui l'a créé... :(

Je vous remercie
Bonne journée
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Remplacer ReceiveNetworkFile

Message par Kwai chang caine »

Bon, j'vois qu'y a pas foule a propos du FTP

J'ai plusieurs questions, qui me turlupine, la au moins vous devez savoir..... :roll:

1/ Parfois je vois des codes avec des aPI "InternetConnect_" et "FtpPutFile_" est ce que c'est la meme chose que l'on soit sur un reseau local ou bien sur internet ????
Ces API sont elles celle qui sont cachées derriere celle de FRED ????

2/ Est ce que la lib FTP de FRED, OpenNetworkConnection() et toutes ses fonctions, peuvent aussi bien se connecter a Google par exemple, ou bien un serveur que l'on créé avec un logiciel freeware comme filezilla, FTP server, ou bien c'est juste pour tourner avec les fonctions de FRED ????

3/ Et si c'est universel....quel est le port utilisé pour les FTP d'internet ???? :roll:

Merci de vos eclaircissements, parce que a force de lire et essayer des dizaines de codes....je m'y perd :(
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Remplacer ReceiveNetworkFile

Message par Cls »

Salut KCC,

1/ Oui c'est le même chose que tu sois sur le net ou sur ton LAN. Ces fonctions ne sont pas celles utilisées par les fonctions natives PB me semble - t - il.

2/ Oui toutes les fonctions réseaux sont compatibles et interconnectables avec d'autres fonctions d'autres langages ou avec les API. A partir du moment où tu as un ReceiveNetworkData et un SendNetworkData, tu peux faire tout ce que tu veux (reste à savoir quel protocole est utilisé pour l'échange des données).

3/ FTP utilise principalement le port 21. Je crois que certaines infos peuvent transiter sur le port 22. Tu peux te référer à la RFC 959 pour plus de détails à ce sujet (là par exemple : http://abcdrfc.free.fr/rfc-vf/rfc959.html ou là : http://www.iprelax.fr/ftp/ftp_rfcfr.php). Il y a surement des RFC complémentaires, donc GIYF ;)

A+
Cls
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Remplacer ReceiveNetworkFile

Message par Kwai chang caine »

Merci beaucoup mon ami et sauveur pro du WEB 8)

Bon bah, deja ça ouvre un eventail drolement large si c'est tout standard, pour pouvoir retrouver un nouveau moteur à mon programme, que j'ai cassé :roll:

Ces API "InternetConnect_" et "FtpPutFile_" etc ...tu crois qu'elle sont derriere les fonctions de FRED ou bien, ce sont d'autres fonctions ??? :roll:
Cette question c'est pour savoir si ça vaut le coup que j'essaie un code avec ces API et un code avec les natives de FRED pour voir si une marche mieux les unes que les autres. :roll:
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Remplacer ReceiveNetworkFile

Message par Cls »

A mon sens tu dois utiliser les fonctions natives de PB.
Je pourrais peut être te filer un coup de main amis plus tard car j'ai beaucoup de travail en ce moment.

Dans l'esprit voici le principe : l'idée est d'envoyer ton fichier en bloc de 512 ou 1024 octets par exemple. Ton client le découpe, créé des paquets des données, y ajoute un entête afin de pouvoir le recomposer et les envoi vers ton serveur.

L'important est de bien gérer les entêtes coté client et coté serveur. Tu peux y mettre le numéro du paquet, un flag pour savoir si c'est le dernier paquet, la place dans le fichier, un code de contrôle des données, etc. Tout dépend comment tu veux gérer ça. Voici un petit schéma d'un paquet potentiel :

+----------------+----------------+----------------+----------------+
| NumPacket (.l) | Position fic (.l) | Flag (.l) | Taille DATAs (.l) |
+----------------+----------------+----------------+----------------+
| DATA |
+----------------+----------------+----------------+----------------+

Voilà c'est un exemple. N'oublie pas que les paquets peuvent arriver dans n'importe quel ordre et qu'il faut donc se fier uniquement aux infos contenus dans l'entête. Si tes données sont sensibles tu peux les chiffrer avant de les envoyer. Tu peux également ajouter un code de contrôle interne pour vérifier l'intégrité des données (checksum). En tout cas, procède étape par étape. Fais quelque chose de simple au début et ajoute progressivement des fonctionnalités.

Bon courage ;)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Remplacer ReceiveNetworkFile

Message par Kwai chang caine »

Merci beaucoup CLS de tes infos. 8)

En fin de compte tout marchais a peu pres bien, mais le probleme c'est apparement quand je refuse des données qui me sont envoyées.
Et ce qui est bizarre c'est que chez moi, ça marche pas comme ils disent dans la doc.

Je créé un buffer de 1000 par exemple.
Et je reçois un truc comme ça 8O

1000
1000
1000
512
1000
512
1000
...
....

FRED y dit que quand le chiffre est plus bas que le buffer c'est que on a tout reçu...
Mais si je m'arette à la premiere "baisse" d'octet, j'ai qu'une partie du fichier.

A lire ce que tu me dit, il ne faut donc pas faire confiance à ce qui est dans la doc :roll:
Et je me demande aussi si y'a pas un probleme de "Timing" car dans tous les codes que je vois, y'a des boucles d'attente.

En fin de compte, comme tu le dit, il faut faire: je reçois un paquet et je dis..."OhhhOhhh j'ai reçu tel paquet" envois la purée (Sous entendu le 2e paquet, etc...)

Une question mega importante pour moi, c'est :
Y'a moyen de vider le buffer FTP, autrement qu'avec les "ReceiveData" pour etre sur que y'a plus rien ???
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Remplacer ReceiveNetworkFile

Message par Cls »

Je ne sais pas comment PB gère sa compote en interne. Ce que tu dis parait bizarre, tout dépend de comment tu envois tes fichiers. Tu utilises quelle commande ?
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Remplacer ReceiveNetworkFile

Message par Kwai chang caine »

Au tout debut, car j'en suis à la 3e version de "moteur"...pire que renault :?

J'utilisais ça :

Lecture du fichier

Code : Tout sélectionner

If ReadFile(#FichierAEnvoyer, FileName)

Detection de sa longueur

Code : Tout sélectionner

LongueurFichier = Lof(#FichierAEnvoyer)
Envoi d'un flag pour dire
1/ Que j'envoi un fichier "EnvoiFichier|"
2/ Le nom du fichier envoyé
3/ Sa longueur

Code : Tout sélectionner

SendNetworkString(ID, "EnvoiFichier|" + NomFichier$ + "|" + Str(LongueurFichier) + Chr(0))
Delay(500)
Apres "J'allocate la mémory" (Joli nouveau verbe :D), J'allocate, tu allocates, nous allocatons....à pas confondre avec ce que certains y abusent avec, les "Allocations" :D

Code : Tout sélectionner

*BufferFichier = AllocateMemory(LongueurFichier)
Je charge le fichier en mémoire et j'envoi

Code : Tout sélectionner

If MemorySize(*BufferFichier) = LongueurFichier
         If ReadData(#FichierAEnvoyer, *BufferFichier, LongueurFichier) = LongueurFichier
          SendNetworkData(ID, *BufferFichier, LongueurFichier)
Et ben je recevais comme je t'ai dit plus haut
Alors j'ai pensé que envoyer d'un coup, tout le fichier, posait des problemes...
Et meme en bloquant à 1000 les "allocations non familliales" et ben pas mieux :(

Alors je me suis dit qu'il se melangeait les pingoinces entre les "SendString" et "SendData"
Car comme juste avant d'envoyer la "répu", j'envoyais un message comme tu dit : "ooh ooohh, j'envoie la puréééééé !!!! et c'est de la vico et y'en a trois paquets"

Et c'est la que les emmerdes ont commencé.....
Pas moyen de vider ce buffer, y restait toujours une cuillere de purée par ci par la.....et a la fin...y savait plus ou il en etait
J'ai vu aussi qu'en rajoutant des delay ça allait un peu mieux....mais bon loin d'etre aussi top que la fonction native de FRED "SendFile" :(

Au fait j'ai oublié de te dire que je suis au boulot, et que nous sommes à la tete d'un monstrueux reseau, avec tout ce qui faut pas : PROXY qui verifie tout et qui m'enpeche de voir les filles nues :mrgreen: , FIREMUR,...... et tout le bataclan, et surtout à la pointe de la technique .....accroche toi bien, a coté la fibre optique c'est de la gnognote, nous on depasse le mur du son à 10 MO :?
D'ailleurs, j'ai vu que ça merdait surtout sur les gros fichiers
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Remplacer ReceiveNetworkFile

Message par Cls »

Humm à vrai dire ça m'étonne qu'à moitié : faire un SendNetworkData sur un gros fichier doit le faire patauger dans la semoule.

J'ai débuter un petit code pour réécrire la fonction d'envoi et de réception. Le voici (il ne sert à rien pour l'instant) :

Code : Tout sélectionner

; ________________________________________________________
;
; Fonctions d'envoi et de réception d'un fichier
;
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

; Auteur : Cls
; Version : Décembre 2009
; Compatibilité : PB 4.40



; Structure de l'entête
Structure NETFILE_HEADER
  no_packet.l
  offset_file.q
  flags.l
  data_size.l
EndStructure


; Configuration
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#READ_BUFFER_SIZE = 1024                         ; Taille du buffer de lecture
#HEADER_SIZE = SizeOf(NETFILE_HEADER)            ; Taille de l'entête
#PACKET_SIZE = #HEADER_SIZE + #READ_BUFFER_SIZE  ; Taille totale d'un packet de données



; Code d'erreurs
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#NETFILE_ERROR_BAD_CONNEXION = $0010
#NETFILE_ERROR_FILE_NOT_FOUND = $0100
#NETFILE_ERROR_FILE_NOT_READABLE = $1000

#INTERNAL_ERROR = $FFFF


; Création de l'entête d'un packet de données
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure PacketCreateHeader(*packet, numero.q, place_fichier.q, taille_donnees.l, drapeaux.l = 0)
  
  *p_packet = *packet
  
  PokeL(*p_packet, numero)         : *p_packet + SizeOf(Long)
  PokeQ(*p_packet, place_fichier)  : *p_packet + SizeOf(Quad)
  PokeL(*p_packet, drapeaux)       : *p_packet + SizeOf(Long)    
  PokeL(*p_packet, taille_donnees) : *p_packet + SizeOf(Long)
  
  ProcedureReturn *packet
EndProcedure


; Ajout des données à un packet
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure PacketAddData(*packet, *donnees.l, taille.l)
  
  *p_packet = *packet
  *p_packet + SizeOf(NETFILE_HEADER)
  
  CopyMemory(*donnees, *p_packet, taille)
  
  ProcedureReturn *packet
EndProcedure


; Lecture de l'entête d'un packet de données
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; @return un pointeur sur une structure de type NETFILE_HEADER
Procedure.l PacketReadHeader(*packet, taille)
  
  header.NETFILE_HEADER = @*packet
  
  ProcedureReturn @header
EndProcedure


; Procédure de DEBUG
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure PacketDebug(*packet, taille.l)
  
  *header.NETFILE_HEADER = *packet

  Debug "No Packet : " + Str(*header\no_packet)
  Debug "Offset : " + Str(*header\offset_file)
  Debug "Flags : " + Str(*header\flags)
  Debug "DATA size : " + Str(*header\data_size)
  
  *packet + SizeOf(NETFILE_HEADER)
  
  str.s
  For x = 0 To taille - SizeOf(NETFILE_HEADER)
    str + Chr(PeekC(*packet + x))
  Next
  
  Debug str
  
EndProcedure


; Procédure d'envoi d'un fichier
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; @param Connexion l'identifiant de la connexion
; @param Fichier le fichier à envoyer
; @param Loopback une fonction permettant de connaitre l'état du transfert (optionel)
; @return 1 si le fichier est envoyé correctement
Procedure SendNetworkFileEx(Connexion.l, Fichier.s, *Loopback.l = #Null)
  
  ; Vérifie la connexion
  If Connexion = 0
    ProcedureReturn #NETFILE_ERROR_BAD_CONNEXION
  EndIf
  
  ; Vérifie le fichier
  total_filesize = FileSize(Fichier)
  If total_filesize < 0
    ProcedureReturn #NETFILE_ERROR_FILE_NOT_FOUND
  EndIf
  
  
  ; Création d'un buffer de lecture
  *read_buffer = AllocateMemory(#READ_BUFFER_SIZE)
  If *read_buffer = 0 
    ProcedureReturn #INTERNAL_ERROR
  EndIf
  
  ; Création d'un buffer pour l'envoi des données (packet)
  *packet = AllocateMemory(#PACKET_SIZE)
  If *packet = 0 
    ProcedureReturn #INTERNAL_ERROR
  EndIf
  
  
  
  ; Handle vers le fichier
  hFile.l = ReadFile(#PB_Any, Fichier)
  If hFile = 0
    ProcedureReturn #NETFILE_ERROR_FILE_NOT_READABLE
  EndIf
  
  
  ; Lit le fichier par bloc
  p_locate_file.q = 0
  numero_packet.l = 0 
  data_send.q = 0
  While Eof(hFile) = 0
  
    ; Lit un bloc de READ_BUFFER
    read_length = ReadData(hFile, *read_buffer, #READ_BUFFER_SIZE)
    
    ;Debug Str(read_length) + " " + Str(p_locate_file)
    
    ; Création d'un paquet de données
    If read_length = #READ_BUFFER_SIZE
      ; Packet "normal"
      *packet = PacketCreateHeader(*packet, numero_packet, p_locate_file, read_length)
    Else
      ; Dernier packet de données
      *packet = PacketCreateHeader(*packet, numero_packet, p_locate_file, read_length, 1)
    EndIf
    
    
    ; Ajout des données à envoyer
    *packet = PacketAddData(*packet, *read_buffer, read_length)
    
    ; Envoi du packet sur le réseau
    ;SendNetworkData(Connexion, *packet, #PACKET_SIZE)
    
    PacketDebug(*packet, #PACKET_SIZE) 
    
    data_send + read_length
    
    ; Appel la loopback
    If *Loopback <> #Null
      CallFunctionFast(*Loopback, data_send, total_filesize)
    EndIf
    
    ; Déplace le pointeur de lecture
    p_locate_file + read_length
    FileSeek(hFile, p_locate_file)
    
    ; Packet suivant
    numero_packet + 1
    
    Delay(1)
    
  Wend

EndProcedure

InitNetwork()

file.s = OpenFileRequester("", "", "", 1)
SendNetworkFileEx(1, file)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Remplacer ReceiveNetworkFile

Message par Kwai chang caine »

Merci mille fois CLS 8)
Et ben.....moi aussi j'ai commencé de mon coté....
Est il besoin de preciser que le miens, ne ressemble pas au tiens qui pourrait presque défiler pour lagarfield :roll:
Bon, je vais essayer d'incorporer ton bijoux dans ma boite a camenbert :oops:

J'avais surtout commencé par créer la structure pour detecter, si le programme est SERVEUR ou CLIENT
Car il faut absolument que ce soit le meme code qui fasse les deux, et en plus, il faut que les deux programmes serveur et client, puissent envoyer et recevoir, comme si ils etaient identiques :D

Pour detecter le mode, je lance le CLIENT en premier et si il n'a pas de serveur au bout, et bien je passe en mode SERVEUR
J'espere que j'ai eu une bonne idée, qu'en penses tu ??? :roll:

Encore merci de ton aide precieuse 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Remplacer ReceiveNetworkFile

Message par Cls »

Attention le code n'est pas du tout terminé. J'attaque actuellement la fonction de réception du fichier, la partie compliquée.

Je te donne des nouvelles dès que possible. ;)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Remplacer ReceiveNetworkFile

Message par Kwai chang caine »

Pas terminé 8O
Et ben dis donc si j'avais des trucs pas terminé comme ça :roll:

D'accord, ne te met pas non plus dans l'embaras pour moi....mais j'attend avec impatience la suite :D
Si tu peux prevoir une fonction pour "vidanger" le buffer en cas de refus du "receveur".

Bon tu va peut etre rire....car ça fait rire tout mes collegues au boulot.
Mes meilleures idées je les ai au toilettes..... :oops:
Je ne sais pas pourquoi, mais peut etre que quand je m'assoie, ça fait un appel d'air....pour le cerveau :roll:
Ou peut etre que c'est parce que j'ai des idées de "merde" :(
Toujours ai t'il, que mes collegues me disent que je ferais bien d'installer mon bureau la-bas :lol:

Bref donc tout à l'heure, assis sur mon trone de porcelaine, je me suis dit : "Nadine bombeck" t'est vraiment un "residu de giclette" ....(C'etait un des surnoms que me donnait mon pere) :oops:, au lieu d'envoyer le couscous, et noyer le buffer de semoule, puis apres demander au "receveur" si y veut de la sauce ou de l'harissa...
Tu ferais mieux de lui demander avant si il a faim :D

En un mot, pourquoi ne pas envoyer une string : "oohh oohh, je vais envoyer tel fichier...t'en veux, gourgandine ???
Et si gourgandine elle repond oui...y'a couscous au repas, sinon bah on envoie rien et comme ça pas de semoule dans le buffer :mrgreen:

Mais bon, ça peut etre quand meme utile un "Leon" de buffer (Nettoyeur), car mieux vaut etre sur que y'a plus rien dedans, car parfois ça foire tout quand y reste quelque chose :?
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Remplacer ReceiveNetworkFile

Message par Cls »

Voilà un code qui fonctionne :
N'hésites pas en cas de besoin ;)

Je vais y ajouter l'implémentation des callbacks ainsi que la gestion d'une barre de progression.

Code : Tout sélectionner

; ________________________________________________________
;
; Fonctions d'envoi et de réception d'un fichier
;
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

; Auteur : Cls
; Version : Décembre 2009
; Compatibilité : PB 4.40



; Structure de l'entête
Structure NETFILE_HEADER
  type.l
  no_packet.l
  offset_file.q
  flags.l
  data_size.l
EndStructure


; Configuration
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#READ_BUFFER_SIZE = 51200                        ; Taille du buffer de lecture
#HEADER_SIZE = SizeOf(NETFILE_HEADER)            ; Taille de l'entête
#PACKET_SIZE = #HEADER_SIZE + #READ_BUFFER_SIZE  ; Taille totale d'un packet de données


; Type de packet de données
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#PACKET_TYPE_FILE_NAME      = $10110001
#PACKET_TYPE_FILE_CONFIRM   = $10110011
#PACKET_TYPE_TRANSFERT_FILE = $10110111


; Code d'erreurs
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#NETFILE_ERROR_BAD_CONNEXION     = $00000010
#NETFILE_ERROR_FILE_NOT_FOUND    = $00000100
#NETFILE_ERROR_FILE_NOT_READABLE = $00001000
#NETFILE_ERROR_FILE_NOT_WRITABLE = $00010000

#INTERNAL_ERROR = $FFFF


; Création d'un packet de données
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure PacketCreate()
  *packet = AllocateMemory(#PACKET_SIZE)
  If *packet = 0 
    ProcedureReturn #INTERNAL_ERROR
  EndIf
  
  ProcedureReturn *packet
EndProcedure


; Création de l'entête d'un packet de données
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure PacketCreateHeader(*packet, type.l, numero.q = 0, place_fichier.q = 0, taille_donnees.l = 0, drapeaux.l = 0)
  
  *p_packet = *packet
  
  PokeL(*p_packet, type)           : *p_packet + SizeOf(Long)
  PokeL(*p_packet, numero)         : *p_packet + SizeOf(Long)
  PokeQ(*p_packet, place_fichier)  : *p_packet + SizeOf(Quad)
  PokeL(*p_packet, drapeaux)       : *p_packet + SizeOf(Long)    
  PokeL(*p_packet, taille_donnees) : *p_packet + SizeOf(Long)
  
  ProcedureReturn *packet
EndProcedure


; Ajout des données à un packet
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure PacketAddData(*packet, *donnees.l, taille.l)
  
  *p_packet = *packet
  *p_packet + SizeOf(NETFILE_HEADER)
  
  CopyMemory(*donnees, *p_packet, taille)
  
  ProcedureReturn *packet
EndProcedure

; Ajout de données de type chaine 
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure PacketAddString(*packet, String.s, taille.l)
  *p_packet = *packet
  *p_packet + SizeOf(NETFILE_HEADER)
  
  PokeL(*p_packet, taille)           : *p_packet + SizeOf(Long)
  PokeS(*p_packet, String, taille)   : *p_packet + taille
  
  ProcedureReturn *packet
EndProcedure


; Procédure de DEBUG d'un paquet
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure PacketDebug(*packet, taille.l)
  
  *header.NETFILE_HEADER = *packet

  Debug "No Packet : " + Str(*header\no_packet)
  Debug "Offset : " + Str(*header\offset_file)
  Debug "Flags : " + Str(*header\flags)
  Debug "DATA size : " + Str(*header\data_size)
  
  *packet + SizeOf(NETFILE_HEADER)
  
  str.s
  For x = 0 To taille - SizeOf(NETFILE_HEADER)
    str + Chr(PeekC(*packet + x))
  Next
  
  Debug str
  
EndProcedure


; Message d'erreur
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure Error(msg.s, type.l = 1)
  Select type
    Case 1
      MessageRequester("Erreur", msg, #MB_ICONINFORMATION)
    Default
      Debug msg
  EndSelect
EndProcedure

; Affichage sur l'IHM
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure Message(msg.s)
  Global log
  msg = FormatDate("%dd/%mm %hh:%ii:%ss", Date()) + " - " + msg
  
  AddGadgetItem(log, -1, msg)
EndProcedure


; Procédure d'envoi d'un fichier
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; @param Connexion l'identifiant de la connexion
; @param Fichier le fichier à envoyer
; @param Fichier_destination le nom du fichier qui sera cré en local
; @param Loopback une fonction permettant de connaitre l'état du transfert (optionel)
; @return 1 si le fichier est envoyé correctement
Procedure SendNetworkFileEx(Connexion.l, Fichier.s, Fichier_destination.s = "", *Loopback.l = #Null)
  
  ; Contrôles
  ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  
  ; Vérifie la connexion
  If Connexion = 0
    ProcedureReturn #NETFILE_ERROR_BAD_CONNEXION
  EndIf
  
  ; Vérifie le fichier
  total_filesize = FileSize(Fichier)
  If total_filesize < 0
    ProcedureReturn #NETFILE_ERROR_FILE_NOT_FOUND
  EndIf
  
  
  ; Création d'un buffer de lecture
  *read_buffer = AllocateMemory(#READ_BUFFER_SIZE)
  If *read_buffer = 0 
    ProcedureReturn #INTERNAL_ERROR
  EndIf
  
  ; Création d'un buffer pour l'envoi des données (packet)
  *packet = PacketCreate()
   
  
  ; Transfert
  ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  ; Handle vers le fichier
  hFile.l = ReadFile(#PB_Any, Fichier)
  If hFile = 0
    ProcedureReturn #NETFILE_ERROR_FILE_NOT_READABLE
  EndIf
  
  
  ; Lit le fichier par bloc
  p_locate_file.q = 0
  numero_packet.l = 0 
  data_send.q = 0
  While Eof(hFile) = 0
  
    ; Lit un bloc de READ_BUFFER
    read_length = ReadData(hFile, *read_buffer, #READ_BUFFER_SIZE)
    
    ;Debug Str(read_length) + " " + Str(p_locate_file)
    
    ; Création d'un paquet de données
    If read_length = #READ_BUFFER_SIZE
      ; Packet "normal"
      *packet = PacketCreateHeader(*packet, #PACKET_TYPE_TRANSFERT_FILE, numero_packet, p_locate_file, read_length)
    Else
      ; Dernier packet de données
      *packet = PacketCreateHeader(*packet, #PACKET_TYPE_TRANSFERT_FILE, numero_packet, p_locate_file, read_length, 1)
    EndIf
    
    ; Ajout des données à envoyer
    *packet = PacketAddData(*packet, *read_buffer, read_length)
    
    ; Envoi du packet sur le réseau
    SendNetworkData(Connexion, *packet, #PACKET_SIZE)
    
    ;PacketDebug(*packet, read_length + #HEADER_SIZE) 
    
    data_send + read_length
    
    ; Appel la loopback
    If *Loopback <> #Null
      CallFunctionFast(*Loopback, data_send, total_filesize)
    EndIf
    
    ; Déplace le pointeur de lecture
    p_locate_file + read_length
    FileSeek(hFile, p_locate_file)
    
    ; Packet suivant
    numero_packet + 1
    
    ; Delay
    Delay(1)
    
  Wend
  
  ; Libération des mémoires
  CloseFile(hFile)
  
  FreeMemory(*read_buffer)
  FreeMemory(*packet)


  ProcedureReturn #True
EndProcedure



; Procédure de reception d'un fichier
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; @param Connexion l'identifiant de la connexion Client
; @param AutoriserNomPersonnalise A true, permet au client de spécifier le nom du fichier
; @param Loopback une fonction permettant de connaitre l'état du transfert (optionel)
; @return 1 si le fichier est recu correctement
Procedure ReceiveNetworkFileEx(Connexion, Fichier.s, *packet.l, length.l, *Loopback.l = #Null)

  ; Contrôles
  ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    
  ; Vérifie la connexion
  If Connexion = 0
    ProcedureReturn #NETFILE_ERROR_BAD_CONNEXION
  EndIf
  
  ; Définition du nom du fichier 
  Fichier_destination.s = Fichier
  
  ; Création d'un buffer d'écriture réception
  *write_buffer = AllocateMemory(#PACKET_SIZE)
  If *write_buffer = 0 
    ProcedureReturn #INTERNAL_ERROR
  EndIf
  
  ; Création d'un buffer contenant le packet entier
  *packet_received = PacketCreate()
  
  
  
  ; Recompose le packet de données 
  ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  CopyMemory(*packet, *packet_received, length)
  
  
  ; Ecriture sur le disque
  ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  
  ; A ce moment *packet contient le packet de données entier
  ;PacketDebug(*packet_received, #PACKET_SIZE)
  
  ; On le réaassemble sur notre disque
  hWriteFile = OpenFile(#PB_Any, "C:\" + Fichier_destination)
  If hWriteFile = 0
    ProcedureReturn #NETFILE_ERROR_FILE_NOT_WRITABLE
  EndIf
  
  ; Entête
  *header.NETFILE_HEADER = *packet_received
  
  ; Données
  *p_packet = *packet_received
  *p_packet + SizeOf(NETFILE_HEADER)

  
  ; Déplace le pointeur d'écriture et écrit les données
  ; Si le pointeur dépasse la fin du fichier, on rempli de vide
  If *header\offset_file > Lof(hWriteFile)
    FileSeek(hWriteFile, Lof(hWriteFile))
    
    taille_to_fill.l = *header\offset_file - Lof(hWriteFile)
    *filler = AllocateMemory(taille_to_fill)
    FillMemory(*filler, taille_to_fill)
    
    WriteData(hWriteFile, *filler, taille_to_fill)
  EndIf
  
  FileSeek(hWriteFile, *header\offset_file) 
  WriteData(hWriteFile, *p_packet, *header\data_size)
  
  ; Libération des mémoires
  CloseFile(hWriteFile)
  
  FreeMemory(*write_buffer)
  FreeMemory(*packet_received)
  
  
EndProcedure


; Sélection et envoi d'un fichier
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure SelectAndSendFile(value.l)
  
  Global client 
  
  file.s = OpenFileRequester("", "", "", 1)
  
  If file
    
    ; Modification du nom du fichier
    ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    
    FileName.s = GetFilePart(file)
    
    *packet = PacketCreate()
    *packet = PacketCreateHeader(*packet, #PACKET_TYPE_FILE_NAME, 0, 0, Len(FileName))
    *packet = PacketAddString(*packet, FileName, Len(FileName))
    SendNetworkData(client, *packet, #PACKET_SIZE)
    
     
    ; Envoi des données au serveur
    ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    SendNetworkFileEx(client, file)
    
    
    ; Confirmation
    ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    *packet = PacketCreate()
    *packet = PacketCreateHeader(*packet, #PACKET_TYPE_FILE_CONFIRM)
    SendNetworkData(client, *packet, #PACKET_SIZE)    
  
  EndIf
  
EndProcedure


; Gère les évènements du serveur
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure ManageNetworkEvent(clientId)
  
  ; Fichier de destination 
  Static Fichier_Destination.s
  

  *packet = PacketCreate()
  length = ReceiveNetworkData(clientId, *packet, #PACKET_SIZE)
  
  *header.NETFILE_HEADER = *packet
  
  Select *header\type
    Case #PACKET_TYPE_FILE_NAME 

      taille_nom_fichier.l = PeekL(*packet + SizeOf(NETFILE_HEADER))
      Fichier_Destination = PeekS(*packet + SizeOf(NETFILE_HEADER) + SizeOf(Long), taille_nom_fichier)
      
      Message("Changement du nom du fichier : " + Fichier_Destination)

    
    Case #PACKET_TYPE_TRANSFERT_FILE
      Message("Données reçues : " + Str(*header\data_size) + " octets")
      ReceiveNetworkFileEx(clientId, Fichier_Destination, *packet, length)
    
    
    Case #PACKET_TYPE_FILE_CONFIRM
      Message("Transfert du fichier terminé !")
    
    Default
      Debug "Packet inconnu"
      
  EndSelect  
  
EndProcedure

;- Début du programe de test

If InitNetwork() = 0 
  Error("Pas de réseau")
  End
EndIf

;file.s = OpenFileRequester("", "", "", 1)
;SendNetworkFileEx(1, file)

; Ouverture d'un écran
#height = 300 : #width = 600
Global window = OpenWindow(#PB_Any, 0, 0, #width, #height, "Test SendNetworkFile / ReceiveNetworkFile par Cls", #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
Global log = ListViewGadget(#PB_Any, 10, 10, #width - 20, #height - 60)
Global send = ButtonGadget(#PB_Any, 10, #height - 40, 150, 30, "Envoyer un fichier...") 

; Création d'un serveur
#port = 5000
Global server = CreateNetworkServer(#PB_Any, #port)
If server : Message("Serveur créé sur le port " + Str(#port)) : EndIf


; Création d'un client
Global client = OpenNetworkConnection("127.0.0.1", #port)


; Boucle des évènements
Quit.l
Repeat
  ;- Evènement fenêtre
  wEvent = WindowEvent()
  Select wEvent
    Case #PB_Event_CloseWindow
      End
    Case #PB_Event_Gadget
      Select EventGadget()
        Case send
          CreateThread(@SelectAndSendFile(), 1)

      EndSelect
  EndSelect
  
  ;- Evènement réseau Serveur
  sEvent = NetworkServerEvent()
  clientId = EventClient()
  Select sEvent
    Case #PB_NetworkEvent_Connect
      Message("Client connecté : " + IPString(GetClientIP(clientId)) + ":" + Str(GetClientPort(clientId)))
      
    Case #PB_NetworkEvent_Data
      ManageNetworkEvent(clientId)
      
    Case #PB_NetworkEvent_Disconnect
      Message("Client déconnecté : " + IPString(GetClientIP(clientId)) + ":" + Str(GetClientPort(clientId)))
      
  EndSelect
  
  ;- Evènement réseau Client
  tEvent = NetworkClientEvent(server)
  Select tEvent
    Case #PB_NetworkEvent_Data
      
  EndSelect
  
  ; On ne vole pas tout le CPU
  Delay(1)
  
Until Quit = 1
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Remplacer ReceiveNetworkFile

Message par Kwai chang caine »

CLS.....je t'aime !!!!! 8)
Image

Il est des moments ou mon silence prend toute sa valeur, c'est "bo" et ça marche 8O

Demain matin au premieres heures, je me jette sur lui pour lui offrir cette splendide boite de bois ronde et odorante que je lui ai préparé :mrgreen:
Je te tiens au courant :wink:
Mon sauveur a écrit :N'hésites pas en cas de besoin
Décidément, tu aimes le danger..... :oops:

Je te souhaite une excelente soirée et te remercie du fond du coeur 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Remplacer ReceiveNetworkFile

Message par Ar-S »

J'espère que tu nous fera part de ton logiciel KCC, à moins que ec soit top secret :mrgreen:
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Répondre