기사 요약:
Delphi는 강력합니다. Delphi로 소프트웨어를 작성하면 소프트웨어 개발 주기를 크게 단축할 수 있습니다. 이 기사에서는 Delphi를 사용하여 지점 간 파일 전송 프로그램을 작성하는 방법을 소개합니다.
-------------------------------------
Delphi는 강력합니다. Delphi로 소프트웨어를 작성하면 소프트웨어 개발 주기를 크게 단축할 수 있습니다. 지점 간 파일 전송의 기본 아이디어는 서버 소프트웨어와 클라이언트 소프트웨어가 동일한 포트를 사용하는 것입니다. 연결된 후 클라이언트는 파일 이름, 크기 등을 포함하여 서버에 요청을 보냅니다. 서버가 파일 전송을 수락하고 시작하는 경우. 물론 파일 전송에는 ASCII 코드와 Bin의 두 가지 모드가 있지만 일반적으로 Bin이면 충분합니다. 위의 논의를 바탕으로 원래 Delphi4의 NMStrm 및 NStrmServ 컨트롤을 사용할 수 있었지만 테스트한 결과 작은 파일에도 NStrm 컨트롤을 사용할 수 있고 파일이 큰 경우(1M) 매우 편리하다는 것을 알았습니다. ) 오류가 발생합니다. 다음으로 Delphi에서 TServerSocket과 TClientSocket을 사용하여 이 프로그램을 작성합니다. 이더넷 패킷 크기의 제한과 DelphiSocket의 처리 메커니즘으로 인해(Delphi에서는 소켓을 사용하여 더 큰 스트림을 보낼 때 수신기가 OnRead를 여러 번 트리거합니다.) . 이벤트가 발생하면 Delphi는 여러 OnRead 이벤트에서 각 데이터의 무결성만을 보장할 뿐 데이터 자체를 수집하여 사용자에게 반환하지 않으므로 하나의 Socket과 Recv에 한 번 전송할 파일을 한 번 보낼 수 있다고 생각하지 마십시오. 또 다른 경우에는 데이터를 직접 수집하거나 프로토콜을 직접 정의해야 하므로 사용자 정의 프로토콜 방식을 채택합니다. 프로토콜을 정의하는 표준적인 방법은 Record End를 사용하는 것입니다. 좋다:
TMyFilePROtocol=기록
sSendType=(ST_QUERY,ST_REFUSE,ST_DATA,ST_ABORT,...);
i길이:정수;
bufSend:버퍼;
끝;
이 방법을 시도해 보았지만 실패했고, 항상 내 방법이 옳다고 생각했는데 프로그램이 항상 컴파일에 실패했습니다. 델파이에 문제가 있었던 것 같습니다 :) 그래서 다음 샘플 프로그램에서는 다른 방법을 사용했습니다. Socket 클래스에는 두 가지 속성(ReceiveText 및 ReceiverBuf)이 있습니다. OnRead 이벤트에서는 이 두 속성을 한 번만 사용할 수 있으므로 전역 변수를 사용하여 Text를 읽을 것인지 Buf를 읽을 것인지, 즉 읽을 수 있는지 저장할 수 있습니다. Buf를 한 번 입력하고 다시 읽으면 TMyFileProtocol을 시뮬레이션합니다.
프로그램을 시작합니다:
주로 방법을 설명하는 데 사용되는 가장 간단한 것을 작성하십시오.
프로토콜 정의:
상수
MP_QUERY ='1';
MP_REFUSE ='2';
MP_ACCEPT ='3';
MP_NEXTWILLBEDATA='4';
MP_DATA ='5';
MP_ABORT ='6';
MP_OVER ='7';
MP_CHAT ='8';
계약 소개:
먼저 클라이언트는 MP_QUERY를 보내고, 이를 받은 후 서버는 MP_ACCEPT 또는 MP_FEFUESE를 보냅니다.
클라이언트는 MP_ACCEPT를 받은 후 MP_FILEPROPERTY를 보내고, 서버는 이를 받은 후 MP_NEXTWILLBEDATA를 보냅니다.
클라이언트는 MP_NEXTWILLBEDATA를 받은 후 보내고, 서버는 받은 후 MP_DATA를 보냅니다.
클라이언트는 MP_DATA를 수신하고 데이터를 전송하며, 서버는 데이터를 수신하고 MP_NEXTWILLBEDATA를 전송합니다.
클라이언트가 MP_OVER를 보낼 때까지 반복합니다.
MP_CHAT+String은 중간에 서로 보낼 수 있습니다.
서버 프로그램:
다음 컨트롤을 배치합니다:SaveDialog1,btnStartServer,
ss,(TServerSocket)
btnStartServer.OnClick(Sender:TObject);
시작하다
ss.포트:=2000;
ss.열기;
끝;
ss.OnClientRead(발신자: TObject;소켓: TCustomWinSocket);
var
s온도:문자열;
bufRecv:포인터;
iRecvLength:정수;
시작하다
bReadText이면
시작하다
sTemp:=Socket.ReceiveText;
케이스 온도[1]
MP_QUERY:시작
//여기서 거부
SaveDialog1.FileName:=Copy(sTemp,2,Length(STemp));
SaveDialog1.Execute이면
시작하다
Socket.SendText(MP_ACCEPT);
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate);
끝
else Socket.SendText(MP_REFUSE+'die');
끝;
MP_FILEPROPERTY:시작
//StrToInt(Copy(sTemp,2,Length(sTemp))) 번을 보내려면
//시간 진행 상황을 표시합니다. . .
Socket.SendText(MP_NEXTWILLBEDATA);
끝;
MP_NEXTWILLBEDATA:시작
Socket.SendText(MP_DATA);
bReadText:=false;
끝;
MP_END:시작
fsRecv.Free
bReadText:=true;
끝;
MP_ABORT:시작
fsRecv.Free;
bReadText:=true;
끝;
MP_CHAT:시작
//채팅 메시지
끝;
끝;{사건의}
끝
그렇지 않으면 시작하다
노력하다
GetMem(bufRecv,2000);//2000은 >iBYTESEND여야 합니다.
Socket.ReceiveBuf(bufRecv^,iRecvLength);
fsRecv.WriteBuffer(bufRecv^,iRecvLength);
마지막으로
FreeMem(bufRecv,2000);
종료;{시도 중}
bReadText:=true;
Socket.SendText(MP_NEXTWILLBEDATA);
끝;
끝;
클라이언트 프로그램:
다음 컨트롤을 배치합니다: edtipAddress, OpenDialog1, btnConnect, btnSendFile,
cs.(TClientSocket)
btnConnect.OnClick(Sender:TObject);
시작하다
cs.Address:=edtIPAddress.Text;
cs.포트:=2000;
cs.연결;
끝;
btnSendFile.OnClick(Sender:TObject);
시작하다
OpenDialog1.Execute이면
시작하다
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);//파일 크기???