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 war es ursprünglich möglich, die NMStrm- und NMStrmServ-Steuerelemente von Delphi4 zu verwenden. Ich habe es jedoch getestet und festgestellt, dass das NMStrm-Steuerelement für kleinere Dateien verwendet werden kann und sehr praktisch ist ), tritt ein Fehler auf. 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. Die kanonische Art, 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, dass meine Methode korrekt sei, 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 Text schreiben und erneut lesen. Dies simuliert TMyFileProtocol.
Starten Sie das Programm:
Schreiben Sie das einfachste, das 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???
Ende;
Ende;
cs.OnRead(Sender: TObject;Socket: TCustomWinSocket);
var
sTemp:string;
bufSend:pointer;
beginnen
sRecv:=Socket.ReceiveText;
Fall sRecv[1] von
MP_REFUSE:ShowMessage('Ohnmacht, sei abgewiesen!');
MP_ACCEPT:beginnen
fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpen);
//iBYTEPERSEND ist eine Konstante, die Größe des jedes Mal gesendeten Pakets.
Socket.SendText(MP_FILEPROPERTY+Trunc(fsSend.Size/iBYTEPERSEND)+1);
Ende;
MP_NEXTWILLBEDATA:beginnen
Socket.SendText(MP_NEXTWILLBEDATA);
Ende;
MP_DATA:beginnen
versuchen
GetMem(bufSend,iBYTEPERSEND+1);
if (fsSend.Position+1+iBYTEPERSEND) < fsSend.Size then
beginnen
fsSend.Read(bufSend^,iBYTEPERSEND);
Socket.SendBuf(bufSend^,iBYTEPERSEND);
fsSend.Free;
Ende // Normales Senden, die Größe beträgt iBYTEPERSEND
sonst beginnen
fsSend.Read(bufSend^,fsSend.Size-fsSend.Position-1);
Socket.SendBuf(bufSend^,fsSend.Size-fsSend.Position-1);
end;//Beim letzten Senden werden die restlichen Daten gesendet
Endlich
FreeMem(bufSend,iBYTEPERSEND+1);
Ende;{des Versuchs}
Ende;
MP_ABORT:beginnen
//Abgesagt :(
fsSend.Free;
Ende;
Ende;{des Falls}
Ende;
Organisationsablauf:
Fügen Sie eine Fehlerbeurteilung hinzu, optimieren Sie das Programm, kombinieren Sie Server und Client, fügen Sie die Anzeige des verbleibenden Zeitfortschritts hinzu, ermöglichen Sie die gleichzeitige Übertragung mehrerer Dateien und fügen Sie eine Chat-Funktion hinzu, um eine gute Punkt-zu-Punkt-Dateiübertragung zu erzielen Programm.