Resumen del artículo:
Delphi es poderoso. Escribir software con Delphi puede acortar enormemente el ciclo de desarrollo de software. Este artículo presenta cómo utilizar Delphi para escribir un programa de transferencia de archivos punto a punto.
-----------------------------------------
Delphi es poderoso. Escribir software con Delphi puede acortar enormemente el ciclo de desarrollo de software. La idea básica de la transferencia de archivos punto a punto es que un software de servidor y un software de cliente utilizan el mismo puerto. Después de conectarse, el cliente envía una solicitud al servidor, incluido el nombre del archivo, el tamaño, etc. el archivo a transferir si el servidor acepta y comienza a transferir archivos. Por supuesto, hay dos modos para la transferencia de archivos, código ASCII y Bin, pero generalmente Bin es suficiente. Según la discusión anterior, originalmente se podía hacer usando los controles NMStrm y NMStrmServ de Delphi4, pero lo probé y descubrí que el control NMStrm aún se puede usar para archivos más pequeños y es muy conveniente, pero si el archivo es grande (1M) , se producirá un error. A continuación, usamos TServerSocket y TClientSocket en Delphi para escribir este programa. Debido a la limitación del tamaño del paquete Ethernet y al mecanismo de procesamiento de DelphiSocket (en Delphi, cuando usa un Socket para enviar un Stream más grande, el receptor activará OnRead varias veces). . evento, Delphi solo garantiza la integridad de cada dato en múltiples eventos OnRead, y no recopila los datos en sí ni los devuelve al usuario, así que no crea que puede enviar el archivo para transferirlo una vez en un Socket y recibirlo una vez. en otro. Debe recopilar los datos usted mismo o definir el protocolo usted mismo), por lo que adoptamos el método de protocolo personalizado. La forma canónica de definir un protocolo es utilizar Record End. como:
TMyFilePRotocol=Registro
sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...);
iLongitud:entero;
buffEnviar:Buffer;
Fin;
Probé este método, pero falló, y siempre pensé que mi método era correcto, pero el programa siempre fallaba al compilar. Supongo que había algún problema con Delphi :) Así que utilicé otro método en el siguiente programa de muestra. Hay dos propiedades, RecibirTexto y RecibirBuf, en la clase Socket. En un evento OnRead, estas dos propiedades solo se pueden usar una vez, por lo que podemos usar una variable global para guardar si leer Texto o Buf, es decir, leer. Envíe un mensaje de texto una vez y léalo nuevamente, esto simula TMyFileProtocol.
Inicie el programa:
Escribe el más simple, utilizado principalmente para explicar el método.
Definir protocolo:
constante
MP_QUERY ='1';
MP_REFUSE ='2';
MP_ACCEPT ='3';
MP_NEXTWILLBEDATA='4';
MP_DATA ='5';
MP_ABORT ='6';
MP_OVER ='7';
MP_CHAT ='8';
Introducción del acuerdo:
Primero, el Cliente envía MP_QUERY, y luego de recibirlo, el Servidor envía MP_ACCEPT o MP_FEFUESE;
El Cliente envía MP_FILEPROPERTY después de recibir MP_ACCEPT, y el Servidor envía MP_NEXTWILLBEDATA después de recibirlo;
El Cliente envía MP_NEXTWILLBEDATA después de recibirlo y el Servidor envía MP_DATA después de recibirlo;
El cliente recibe MP_DATA y envía datos, el servidor recibe datos y envía MP_NEXTWILLBEDATA;
Repita hasta que el Cliente envíe MP_OVER;
MP_CHAT+String se puede enviar entre sí en el medio;
Programa de servidor:
Coloque los siguientes controles:SaveDialog1,btnStartServer,
ss,(TServerSocket)
btnStartServer.OnClick(Remitente:TObject);
comenzar
ss.Puerto:=2000;
ss.Abierto;
fin;
ss.OnClientRead(Remitente: TObject;Socket: TCustomWinSocket);
var
sTemp:cadena;
bufRecv:Puntero;
iRecvLength: entero;
comenzar
si bReadText entonces
comenzar
sTemp:=Socket.ReceiveText;
caso sTemp[1] de
MP_QUERY:comenzar
//Rechazar aquí
SaveDialog1.FileName:=Copiar(sTemp,2,Longitud(STemp));
si SaveDialog1.Execute entonces
comenzar
Socket.SendText(MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
fin
else Socket.SendText(MP_REFUSE+'die');
fin;
MP_FILEPROPERTY:comenzar
//Para enviar StrToInt(Copy(sTemp,2,Length(sTemp))) veces
// Visualización del progreso del tiempo. . .
Socket.SendText(MP_NEXTWILLBEDATA);
fin;
MP_NEXTWILLBEDATA:comenzar
Socket.SendText(MP_DATA);
bReadText:=falso;
fin;
MP_END:comenzar
fsRecv.Free
bReadText:=verdadero;
fin;
MP_ABORT:comenzar
fsRecv.Gratis;
bReadText:=verdadero;
fin;
MP_CHAT:comenzar
//Mensaje de chat
fin;
fin; {de caso}
fin
si no, empezar
intentar
GetMem(bufRecv,2000);//2000 debe >iBYTESEND
Socket.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
finalmente
FreeMem(bufRecv,2000);
fin; {de intentar}
bReadText:=verdadero;
Socket.SendText(MP_NEXTWILLBEDATA);
fin;
fin;
Programa cliente:
Coloque los siguientes controles: editipAddress, OpenDialog1, btnConnect, btnSendFile,
cs.(TClientSocket)
btnConnect.OnClick(Remitente:TObject);
comenzar
cs.Address:=edtIPAddress.Text;
cs.Puerto:=2000;
cs.Conectar;
fin;
btnSendFile.OnClick(Remitente:TObject);
comenzar
si OpenDialog1.Execute entonces
Comenzar
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);//FileSize???