Delphi est puissant. L'écriture de logiciels avec Delphi peut considérablement raccourcir le cycle de développement logiciel. L'idée de base du transfert de fichiers point à point est qu'un logiciel serveur et un logiciel client utilisent le même port. Après avoir été connecté, le client envoie une requête au serveur, comprenant le nom du fichier, la taille, etc. le fichier à transférer. Si le serveur accepte et commence le transfert de fichiers. Bien entendu, il existe deux modes de transfert de fichiers, le code ASCII et Bin, mais généralement Bin suffit. Sur la base de la discussion ci-dessus, il était à l'origine possible d'utiliser les contrôles NMStrm et NMStrmServ de Delphi4. Cependant, je l'ai testé et j'ai constaté que le contrôle NMStrm peut être utilisé pour des fichiers plus petits et est très pratique, cependant, si le fichier est volumineux (1 Mo). ), une erreur se produira. Nous utilisons donc ensuite TServerSocket et TClientSocket dans Delphi pour écrire ce programme. En raison de la limitation de la taille des paquets Ethernet et du mécanisme de traitement de DelphiSocket (dans Delphi, lorsque vous utilisez un Socket pour envoyer un flux plus volumineux, le récepteur déclenchera OnRead plusieurs fois. . événement, Delphi garantit uniquement l'intégrité de chaque donnée dans plusieurs événements OnRead, et ne collecte pas les données lui-même et ne les renvoie pas à l'utilisateur, alors ne pensez pas que vous pouvez envoyer le fichier à transférer une fois dans un Socket et Recv une fois dans un autre. Vous devez collecter les données vous-même ou définir le protocole vous-même), nous adoptons donc la méthode du protocole personnalisé. La manière canonique de définir un protocole consiste à utiliser Record End. comme:
TMyFilePRotocol=Enregistrer
sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...);
iLongueur : entier ;
bufSend:Tampon;
Fin;
J'ai essayé cette méthode, mais elle a échoué, et j'ai toujours pensé que ma méthode était correcte, mais la compilation du programme échouait toujours. Je suppose qu'il y avait un problème avec Delphi :) J'ai donc utilisé une autre méthode dans l'exemple de programme suivant. Il existe deux propriétés, ReceiverText et ReceiverBuf, dans la classe Socket. Dans un événement OnRead, ces deux propriétés ne peuvent être utilisées qu'une seule fois, nous pouvons donc utiliser une variable globale pour enregistrer s'il faut lire Text ou Buf, c'est-à-dire lire. Envoyez un message une fois et relisez-le Buf, cela simule TMyFileProtocol.
Démarrez le programme :
Écrivez le plus simple, principalement utilisé pour expliquer la méthode.
Définir le protocole :
Const
MP_QUERY ='1';
MP_REFUSE ='2';
MP_ACCEPT ='3';
MP_NEXTWILLBEDATA='4';
MP_DATA = '5';
MP_ABORT ='6';
MP_OVER = '7';
MP_CHAT ='8';
Présentation de l'accord :
Tout d'abord, le client envoie MP_QUERY, et après l'avoir reçu, le serveur envoie MP_ACCEPT ou MP_FEFUESE ;
Le client envoie MP_FILEPROPERTY après avoir reçu MP_ACCEPT, et le serveur envoie MP_NEXTWILLBEDATA après l'avoir reçu ;
Le client envoie MP_NEXTWILLBEDATA après l'avoir reçu, et le serveur envoie MP_DATA après l'avoir reçu ;
Le client reçoit MP_DATA et envoie des données, le serveur reçoit des données et envoie MP_NEXTWILLBEDATA ;
Boucle jusqu'à ce que le client envoie MP_OVER ;
MP_CHAT+String peuvent être envoyés entre eux au milieu ;
Programme serveur :
Placez les contrôles suivants : SaveDialog1,btnStartServer,
ss,(TServerSocket)
btnStartServer.OnClick(Expéditeur:TObject);
commencer
ss.Port :=2000 ;
ss.Ouvert ;
fin;
ss.OnClientRead(Expéditeur : TObject;Socket : TCustomWinSocket) ;
var
sTemp:chaîne;
bufRecv:Pointeur;
iRecvLength:entier;
commencer
si bLireTexte alors
commencer
sTemp:=Socket.ReceiveText;
cas sTemp[1] de
MP_QUERY : début
//Rejeter ici
SaveDialog1.FileName:=Copie(sTemp,2,Length(STemp));
si SaveDialog1.Execute alors
commencer
Socket.SendText(MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
fin
sinon Socket.SendText(MP_REFUSE+'die');
fin;
MP_FILEPROPERTY : début
//Pour envoyer StrToInt(Copy(sTemp,2,Length(sTemp))) fois
//Affichage de la progression du temps. . .
Socket.SendText(MP_NEXTWILLBEDATA);
fin;
MP_NEXTWILLBEDATA : début
Socket.SendText(MP_DATA);
bReadText:=faux;
fin;
MP_END : début
fsRecv.Gratuit
bReadText : = vrai ;
fin;
MP_ABORT : début
fsRecv.Free;
bReadText : = vrai ;
fin;
MP_CHAT : début
//Message de discussion
fin;
fin ;{du cas}
fin
sinon commencer
essayer
GetMem(bufRecv,2000);//2000 doit >iBYTESEND
Socket.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
enfin
FreeMem(bufRecv,2000);
fin ;{d'essai}
bReadText : = vrai ;
Socket.SendText(MP_NEXTWILLBEDATA);
fin;
fin;
Programme client :
Placez les contrôles suivants : edtipAddress, OpenDialog1, btnConnect, btnSendFile,
cs. (TClientSocket)
btnConnect.OnClick(Expéditeur:TObject);
commencer
cs.Address:=edtIPAddress.Text;
cs.Port :=2000 ;
cs.Connect;
fin;
btnSendFile.OnClick(Expéditeur:TObject);
commencer
si OpenDialog1.Execute alors
Commencer
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);//FileSize???
fin;
fin;
cs.OnRead (Expéditeur : TObject ; Socket : TCustomWinSocket) ;
var
sTemp:chaîne;
bufSend: pointeur;
commencer
sRecv:=Socket.ReceiveText;
Cas sRecv[1] de
MP_REFUSE:ShowMessage('Évanouissement, être refusé !');
MP_ACCEPT : début
fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpen);
//iBYTEPERSEND est une constante, la taille du paquet envoyé à chaque fois.
Socket.SendText(MP_FILEPROPERTY+Trunc(fsSend.Size/iBYTEPERSEND)+1);
fin;
MP_NEXTWILLBEDATA : début
Socket.SendText(MP_NEXTWILLBEDATA);
fin;
MP_DATA : début
essayer
GetMem(bufSend,iBYTEPERSEND+1);
si (fsSend.Position+1+iBYTEPERSEND) < fsSend.Size alors
commencer
fsSend.Read(bufSend^,iBYTEPERSEND);
Socket.SendBuf(bufSend^,iBYTEPERSEND);
fsSend.Free;
fin//Envoi ordinaire, la taille est iBYTEPERSEND
sinon commencer
fsSend.Read(bufSend^,fsSend.Size-fsSend.Position-1);
Socket.SendBuf(bufSend^,fsSend.Size-fsSend.Position-1);
fin;//La dernière fois à envoyer, envoyer les données restantes
enfin
FreeMem(bufSend,iBYTEPERSEND+1);
fin ;{d'essai}
fin;
MP_ABORT : début
//Annulé :(
fsSend.Free;
fin;
fin ;{du cas}
fin;
Procédure d'organisation :
Ajoutez un jugement d'erreur, optimisez le programme, combinez le serveur et le client, ajoutez l'affichage de la progression du temps restant, permettez de transférer plusieurs fichiers en même temps et ajoutez une fonction de discussion, et cela devient un bon transfert de fichiers point à point. programme.