Resumo do artigo:
Delphi é poderoso. Escrever software com Delphi pode reduzir bastante o ciclo de desenvolvimento de software. Este artigo apresenta como usar Delphi para escrever um programa de transferência de arquivos ponto a ponto.
-----------------------------------------------
Delphi é poderoso. Escrever software com Delphi pode reduzir bastante o ciclo de desenvolvimento de software. A ideia básica da transferência de arquivos ponto a ponto é que um software servidor e um software cliente usem a mesma porta. Depois de conectado, o cliente envia uma solicitação ao servidor, incluindo o nome do arquivo, tamanho, etc. o arquivo a ser transferido Se o servidor aceitar e iniciar a transferência de arquivos. Claro, existem dois modos de transferência de arquivos, código ASCII e Bin, mas geralmente Bin é suficiente. Com base na discussão acima, originalmente isso poderia ser feito usando os controles NMStrm e NMStrmServ do Delphi4, mas eu testei e descobri que o controle NMStrm ainda pode ser usado para arquivos menores e é muito conveniente, mas se o arquivo for grande (1M) , ocorrerá um erro. Então, a seguir, usamos TServerSocket e TClientSocket no Delphi para escrever este programa. Devido à limitação do tamanho do pacote Ethernet e ao mecanismo de processamento do DelphiSocket (no Delphi, quando você usa um Socket para enviar um Stream maior, o receptor irá acionar OnRead várias vezes. . evento, o Delphi apenas garante a integridade de cada dado em vários eventos OnRead, e não coleta os dados em si e os devolve ao usuário, então não pense que você pode enviar o arquivo para ser transferido uma vez em um Socket e Recv uma vez em outro, você mesmo deve coletar os dados ou definir o protocolo), então adotamos o método de protocolo personalizado. A maneira canônica de definir um protocolo é usar Record End. como:
TMyFilePRotocol=Registro
sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...);
iComprimento: inteiro;
bufEnviar:Buffer;
Fim;
Eu tentei esse método, mas ele falhou, e sempre pensei que meu método estava correto, mas o programa sempre falhava ao compilar. Acho que havia algo errado com o Delphi :) Então usei outro método no programa de exemplo a seguir. Existem duas propriedades, ReceiveText e ReceiveBuf, na classe Socket. Em um evento OnRead, essas duas propriedades só podem ser usadas uma vez, portanto podemos usar uma variável global para salvar se devemos ler Text ou Buf, ou seja, ler. Envie uma mensagem de texto uma vez e leia novamente Buf, isso simula TMyFileProtocol.
Inicie o programa:
Escreva o mais simples, usado principalmente para explicar o método.
Definir protocolo:
Const.
MP_QUERY='1';
MP_REFUSE ='2';
MP_ACEITAR ='3';
MP_NEXTWILLBEDATA='4';
MP_DADOS ='5';
MP_ABORT='6';
MP_OVER='7';
MP_CHAT='8';
Introdução do acordo:
Primeiramente o Cliente envia MP_QUERY, e após recebê-lo o Servidor envia MP_ACCEPT ou MP_FEFUESE;
O Cliente envia MP_FILEPROPERTY após receber MP_ACCEPT, e o Servidor envia MP_NEXTWILLBEDATA após recebê-lo;
O Cliente envia MP_NEXTWILLBEDATA após recebê-lo, e o Servidor envia MP_DATA após recebê-lo;
Cliente recebe MP_DATA e envia dados, Servidor recebe dados e envia MP_NEXTWILLBEDATA;
Loop até que o cliente envie MP_OVER;
MP_CHAT+String podem ser enviados um ao outro no meio;
Programa de servidor:
Coloque os seguintes controles:SaveDialog1,btnStartServer,
ss,(TServerSocket)
btnStartServer.OnClick(Sender:TObject);
começar
ss.Porta:=2000;
ss.Abrir;
fim;
ss.OnClientRead(Remetente: TObject;Socket: TCustomWinSocket);
var
temperatura:string;
bufRecv:Ponteiro;
iRecvLength:inteiro;
começar
se bReadText então
começar
sTemp:=Socket.ReceiveText;
caso Temp[1] de
MP_QUERY:início
//Rejeite aqui
SaveDialog1.FileName:=Copiar(sTemp,2,Comprimento(STemp));
se SaveDialog1.Execute então
começar
Socket.SendText(MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
fim
senão Socket.SendText(MP_REFUSE+'die');
fim;
MP_FILEPROPERTY:início
//Para enviar StrToInt(Copy(sTemp,2,Length(sTemp))) vezes
//Exibição do progresso do tempo. . .
Socket.SendText(MP_NEXTWILLBEDATA);
fim;
MP_NEXTWILLBEDATA:início
Socket.SendText(MP_DATA);
bReadText:=falso;
fim;
MP_END:início
fsRecv.Free
bReadText:=true;
fim;
MP_ABORT:início
fsRecv.Free;
bReadText:=true;
fim;
MP_CHAT:início
//Mensagem de bate-papo
fim;
fim;{do caso}
fim
senão começar
tentar
GetMem(bufRecv,2000);//2000 deve >iBYTESEND
Socket.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
finalmente
FreeMem(bufRecv,2000);
fim;{de tentativa}
bReadText:=true;
Socket.SendText(MP_NEXTWILLBEDATA);
fim;
fim;
Programa cliente:
Coloque os seguintes controles: edtipAddress, OpenDialog1, btnConnect, btnSendFile,
cs.(TClientSocket)
btnConnect.OnClick(Sender:TObject);
começar
cs.Address:=edtIPAddress.Text;
cs.Port:=2000;
cs.Conectar;
fim;
btnSendFile.OnClick(Sender:TObject);
começar
se OpenDialog1.Execute então
Começar
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName); //Tamanho do arquivo???