Re: Remplacer ReceiveNetworkFile
Publié : mar. 15/déc./2009 19:14
Top secret c'est un grand mot.....mais c'est pour mon boulot 

Forums PureBasic - Français
http://forums.purebasic.com/french/
Dechire sa mere, dechire sa mere ....j'ai pas dit çavenom a écrit :Definition dérivatif
en gros que tu fasse un dériver ou carrément nous montrer ton projet qui d'après toi "déchire sa mère"![]()
![]()
venom a écrit :je sais bien que tu n'a pas dit cela
Ahhh bon !!!!Un geek est un homme qui croit que 1 kilomètre est égale a 1024 mètre
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
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#Destination_Directory = "C:\"
#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
#PACKET_TYPE_MD5 = $10111111
; 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.q = 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)
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, #Destination_Directory + 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)
; Appel de la CallBack
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
If *Loopback <> #Null
CallFunctionFast(*Loopback)
EndIf
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, FileSize(file), Len(FileName))
*packet = PacketAddString(*packet, FileName, Len(FileName))
SendNetworkData(client, *packet, #PACKET_SIZE)
; Envoi des données au serveur
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
ret = SendNetworkFileEx(client, file)
If ret <> 1
Error(Str(ret))
Else
; Confirmation
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*packet = PacketCreate()
*packet = PacketCreateHeader(*packet, #PACKET_TYPE_FILE_CONFIRM)
SendNetworkData(client, *packet, #PACKET_SIZE)
; Vérification de l'intégrité du fichier
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
md5.s = MD5FileFingerprint(file)
*packet = PacketCreate()
*packet = PacketCreateHeader(*packet, #PACKET_TYPE_MD5)
*packet = PacketAddString(*packet, md5, Len(md5))
SendNetworkData(client, *packet, #PACKET_SIZE)
EndIf
EndIf
EndProcedure
; Met à jour la barre de progression
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure RefreshProgressBar(Transfert.q, Total.q)
Global progress, progress_text
pourcentage.f = Transfert / Total * 100
SetGadgetText(progress_text, Str(pourcentage) + " %")
SetGadgetState(progress, pourcentage)
EndProcedure
Procedure CheckMd5FileFingerPrint(md5.s, file.s)
If MD5FileFingerprint(file) = md5
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
; Gère les évènements du serveur
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Procedure ManageNetworkEvent(clientId)
Static Fichier_Destination.s ; Fichier de destination
Static Fichier_Taille.q ; Taille totale du fichier
Static Fichier_Transfere.q ; Taille reçue
*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)
Fichier_Taille = *header\offset_file ; On utilise ce champ pour envoyer la taille du fichier
Fichier_Transfere = 0
Message("Changement du nom du fichier : " + Fichier_Destination + " (" + Str(Fichier_Taille) + " octets)")
Case #PACKET_TYPE_TRANSFERT_FILE
Message("Données reçues : " + Str(*header\data_size) + " octets")
ReceiveNetworkFileEx(clientId, Fichier_Destination, *packet, length)
Fichier_Transfere + *header\data_size
RefreshProgressBar(Fichier_Transfere, Fichier_Taille)
Case #PACKET_TYPE_FILE_CONFIRM
Message("Transfert du fichier terminé !")
Case #PACKET_TYPE_MD5
taille_md5.l = PeekL(*packet + SizeOf(NETFILE_HEADER))
MD5.s = PeekS(*packet + SizeOf(NETFILE_HEADER) + SizeOf(Long), taille_md5)
If CheckMd5FileFingerPrint(MD5, #Destination_Directory + Fichier_Destination)
Message("L'empreinte MD5 du fichier est correcte. Le fichier a été transféré correctement.")
Else
Message("Le fichier est corrompu ! :(")
EndIf
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 = 350 : #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 - 75)
Global progress = ProgressBarGadget(#PB_Any, 10, #height - 60, #width - 20, 10, 0, 100, #PB_ProgressBar_Smooth)
Global progress_text = TextGadget(#PB_Any, #width - 40, #height - 40, 30, 20, "0 %")
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 = WaitWindowEvent(1)
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
Until Quit = 1