Zusammenfassung des Artikels:
Delphi ist leistungsstark. Das Schreiben von Software mit Delphi kann den Softwareentwicklungszyklus erheblich verkürzen. In diesem Artikel wird erläutert, wie Sie mit Delphi ein Punkt-zu-Punkt-Dateiübertragungsprogramm schreiben.
-----------------------------------------------
Delphi ist leistungsstark. Das Schreiben von Software mit Delphi kann den Softwareentwicklungszyklus erheblich verkürzen. Die Grundidee der Punkt-zu-Punkt-Dateiübertragung besteht darin, dass eine Serversoftware und eine Clientsoftware denselben Port verwenden. Nach der Verbindung sendet der Client eine Anfrage an den Server, einschließlich Dateiname, Größe usw Die zu übertragende Datei wird vom Server akzeptiert und mit der Übertragung der Dateien begonnen. Natürlich gibt es zwei Modi für die Dateiübertragung, ASCII-Code und Bin, aber im Allgemeinen reicht Bin aus. Basierend auf der obigen Diskussion könnte dies ursprünglich mit den Steuerelementen NMStrm und NMStrmServ von Delphi4 erfolgen, aber ich habe es getestet und festgestellt, dass das NMStrm-Steuerelement immer noch für kleinere Dateien verwendet werden kann und sehr praktisch ist, aber wenn die Datei groß ist (1 MB). , wird ein Fehler auftreten. Als nächstes verwenden wir TServerSocket und TClientSocket in Delphi, um dieses Programm zu schreiben. Aufgrund der Beschränkung der Ethernet-Paketgröße und des Verarbeitungsmechanismus von DelphiSocket (in Delphi löst der Empfänger OnRead mehrmals aus, wenn Sie einen Socket zum Senden eines größeren Streams verwenden). . Bei diesem Ereignis garantiert Delphi nur die Integrität aller Daten in mehreren OnRead-Ereignissen und sammelt die Daten nicht selbst und gibt sie nicht an den Benutzer zurück. Denken Sie also nicht, dass Sie die zu übertragende Datei einmal in einem Socket und einmal in Recv senden können in einem anderen Fall müssen Sie die Daten selbst sammeln oder das Protokoll selbst definieren. Daher verwenden wir die benutzerdefinierte Protokollmethode. Der kanonische Weg, ein Protokoll zu definieren, ist die Verwendung von Record End. wie:
TMyFilePRotocol=Aufzeichnen
sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...);
iLength:integer;
bufSend:Puffer;
Ende;
Ich habe diese Methode ausprobiert, aber sie ist fehlgeschlagen, und ich dachte immer, meine Methode sei korrekt, aber das Programm konnte immer nicht kompiliert werden. Ich vermute, dass mit Delphi etwas nicht stimmte:) Deshalb habe ich im folgenden Beispielprogramm eine andere Methode verwendet. In der Socket-Klasse gibt es zwei Eigenschaften, ReceiveText und ReceiveBuf. In einem OnRead-Ereignis können diese beiden Eigenschaften nur einmal verwendet werden, sodass wir eine globale Variable verwenden können, um zu speichern, ob Text oder Buf gelesen werden soll Einmal schreiben und noch einmal lesen, das simuliert TMyFileProtocol.
Starten Sie das Programm:
Schreiben Sie den einfachsten Text, der hauptsächlich zur Erläuterung der Methode verwendet wird.
Protokoll definieren:
Konst
MP_QUERY ='1';
MP_REFUSE ='2';
MP_ACCEPT ='3';
MP_NEXTWILLBEDATA='4';
MP_DATA ='5';
MP_ABORT ='6';
MP_OVER ='7';
MP_CHAT ='8';
Vereinbarungseinführung:
Zuerst sendet der Client MP_QUERY und nach dem Empfang sendet der Server MP_ACCEPT oder MP_FEFUESE;
Der Client sendet MP_FILEPROPERTY, nachdem er MP_ACCEPT empfangen hat, und der Server sendet MP_NEXTWILLBEDATA, nachdem er es empfangen hat.
Der Client sendet MP_NEXTWILLBEDATA nach dem Empfang und der Server sendet MP_DATA nach dem Empfang.
Der Client empfängt MP_DATA und sendet Daten, der Server empfängt Daten und sendet MP_NEXTWILLBEDATA;
Schleife, bis der Client MP_OVER sendet;
MP_CHAT+String kann in der Mitte aneinander gesendet werden;
Serverprogramm:
Platzieren Sie die folgenden Steuerelemente:SaveDialog1,btnStartServer,
ss,(TServerSocket)
btnStartServer.OnClick(Sender:TObject);
beginnen
ss.Port:=2000;
ss.Offen;
Ende;
ss.OnClientRead(Sender: TObject;Socket: TCustomWinSocket);
var
sTemp:string;
bufRecv:Pointer;
iRecvLength:integer;
beginnen
wenn bReadText dann
beginnen
sTemp:=Socket.ReceiveText;
case sTemp[1] von
MP_QUERY:beginnen
//Hier ablehnen
SaveDialog1.FileName:=Copy(sTemp,2,Length(STemp));
wenn SaveDialog1.Execute dann
beginnen
Socket.SendText(MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
Ende
else Socket.SendText(MP_REFUSE+'die');
Ende;
MP_FILEPROPERTY:beginnen
//Um StrToInt(Copy(sTemp,2,Length(sTemp))) mal zu senden
//Zeitfortschrittsanzeige. . .
Socket.SendText(MP_NEXTWILLBEDATA);
Ende;
MP_NEXTWILLBEDATA:beginnen
Socket.SendText(MP_DATA);
bReadText:=false;
Ende;
MP_END:beginnen
fsRecv.Free
bReadText:=true;
Ende;
MP_ABORT:beginnen
fsRecv.Free;
bReadText:=true;
Ende;
MP_CHAT:beginnen
//Chat-Nachricht
Ende;
Ende;{des Falls}
Ende
sonst beginnen
versuchen
GetMem(bufRecv,2000);//2000 muss >iBYTESEND sein
Socket.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
Endlich
FreeMem(bufRecv,2000);
Ende;{des Versuchs}
bReadText:=true;
Socket.SendText(MP_NEXTWILLBEDATA);
Ende;
Ende;
Kundenprogramm:
Platzieren Sie die folgenden Steuerelemente: edtipAddress, OpenDialog1, btnConnect, btnSendFile,
cs. (TClientSocket)
btnConnect.OnClick(Sender:TObject);
beginnen
cs.Address:=edtIPAddress.Text;
cs.Port:=2000;
cs.Connect;
Ende;
btnSendFile.OnClick(Sender:TObject);
beginnen
wenn OpenDialog1.Execute dann
Beginnen
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);//FileSize???