|
감사합니다
NonBlocking ThreadBlocking 에 대해서는 많은 도움이 된것 같습니다.
그런데 님에 code에도 전송되는 Data에 전송중에 Data가 변형되거나 깨어지거나 하는 경우는 고려가 되어있지 않네요
1024Byte씩 전송하고 있는데 수신측에 Data가 송신측의 Data와 100% 항상 똑같다고 할수는 없잖아요?
제 경우 파일전송부분에 CheckSum을 추가했습니다.
------------------------------------------------------------------------------
#define MAX_BUFFER_SIZE 1024
void __fastcall TFileSendThread::Execute()
{
TFileStream* pStream;
char pBuff[MAX_BUFFER_SIZE];
int nCopySize;
char chkSum;
Main->Pb_Tx->Position = 0;
String fname=ExtractFileName(TxFileName);
int fsize,txsize=0;
try
{
pStream = new TFileStream(TxFileName, fmOpenRead);
fsize= pStream->Size;
Main->Pb_Tx->Max = pStream->Size;
Main->ClientSocket->Socket->SendText(fname + "," + IntToStr(pStream->Size)+"@");
while (true)
{
nCopySize = pStream->Read(pBuff, MAX_BUFFER_SIZE);
txsize+=nCopySize;
chkSum=pBuff[0];
for(int i=1;i<nCopySize;i++) chkSum=chkSum^pBuff[i]; //체크섬을 만든다.
pBuff[nCopySize] =chkSum;
pBuff[nCopySize+1] = '\0';
if (nCopySize != 0)
Main->ClientSocket->Socket->SendBuf(pBuff, MAX_BUFFER_SIZE+1); //1024+1 Byte씩 전송
else
break;
}
Application->ProcessMessages();
if(Main->ErrPacket->Count>0)
{
int packet=StrToInt(Main->ErrPacket->Strings[0]);
pStream->Seek(packet*1024,soFromBeginning );
nCopySize = pStream->Read(pBuff, MAX_BUFFER_SIZE);
chkSum=pBuff[0];
for(int i=1;i<nCopySize;i++)
chkSum=chkSum^pBuff[i];
pBuff[nCopySize] =chkSum;
pBuff[nCopySize+1] =packet/256;
pBuff[nCopySize+2] =packet%256;
pBuff[nCopySize+3] = '\0';
Main->ClientSocket->Socket->SendBuf(pBuff, nCopySize+3); //1024+3Byte씩 전송
Main->ErrPacket->Delete(0);
}
}
__finally
{
delete pStream;
}
Main->ClientSocket->Socket->SendText("");
Main->Memo_Tx->Lines->Add("파일송신 끝");
Main->Memo_Tx->Lines->Add("파일Size:"+IntToStr(fsize));
Main->Memo_Tx->Lines->Add("파일TxSize:"+IntToStr(txsize));
}
--------------------------------------------------------------------------
---------------------수신측에서는 -----------------------------------------
전체 수신Data에서 맨마지막 Data까지 XOR를 한후에 그것과 맨마지막 Byte와 비교합니다.
여기서 똑같지 않으며 다시 전송해달라고 요청하지요
송신측에서는 재전송요청 Message를 위에 code에서는 ErrPacket이라는 TStringList에 담아둡니다.
-------------------------------------------------------------------------
Error는 종종발생하더라구요
송수신측 모두 Local이거나 File크기가 작을때는 적게 나타나는데
File 크기가 커질수록 자주 나타나더라구요
이점한 님이 쓰신 글 :
: 사람들은 TServerSocket의 쓰레드블럭킹의 강력함을 잘 모르더군요.
: 우리나라에서는 소스 조차 찾기 힘들고 외국 소스 몇개 참조 했는데
: 제대로 정리해서 강좌식으로 올리려고 작년부터 마음 먹었었는데 시간이 안되
: 못올리는군요. 아예 소스를 첨부 할테니 내용 참조 하세요.
: TServerSocket의 쓰레드 블럭킹 예제입니다.
: 소스 내의 디렉토리 몇개는 바꾸셔야 할것입니다. 다운 로드 폴더를 임의로 "C:\temp"로 했거든요.
: 바로 쓰실려면 아마 "C:\temp"라는 디렉토리 만들어 두셔야 할 것입니다.
: 현재 피시방 관리프로그램이랑 휴대폰 결제 프로그램에 응용해서 사용 되고 있는 루틴입니다.
: Project1은 쓰레드블럭킹을 이용하는 서버구요. Project2는 클라이언트입니다.
: 쓰레드에서 스트리밍 전송이 되기 때문에 여러 사용자 동시 다운로드도 가능합니다.
: 보통 NonBlocking으로 하면 다운로드 중에 다른 사용자가 다운로드 시도하면 첫번째넘은 일시정지
: 되는데 쓰레드 블럭킹은 전혀 그런것 없습니다.
:
: 일단 소스 첨부 해드릴테니깐 잘 참조 하세요. 생각외로 소스는 간단하답니다.
:
: 앞으로 시간이 되면 스레드블럭킹에 대한 자세한 강좌를 약속드리며....
:
: 참 구글 같은데서 "ClientSocket->"이거나 "TMyServerThread" 이거로 검색 하시면 제꺼와
: 유사한 소스는 몇개 찾으실겁니다. 주로 일본이나 미국 볼랜드포럼 개발자 사이트가 많이 나오더군요.
:
:
: 장성호 님이 쓰신 글 :
: : 안녕하세요
: : 소켓으로 파일 전송하고자 합니다.
: : (참고할수 있는 자료나 책같은것이라도 소개 좀 부탁드립니다.)
: :
: : C++Builder의 TServerSocket과 TClientSocket을 쓰고있습니다.
: :
: : 맨처음 File Name과 File Size를 전송합니다.
: :
: : 그다음 File을 일정한 크기(1024BYte)씩 짤라서 전송합니다.
: : 그런데 가끔 전송중간에 Error가 나는수 있더라구요
: : 그것을 확인하기 위해 Data맨뒤에 CheckSum을 1Byte추가했습니다.
: : CheckSum은 모든Data를 XOR했구요
: :
: : Data를 수신한후 CheckSum에 문제가 있으면
: : 해당Packet을 다시 전송해달라고 송신측에 메세지를 보냅니다.
: :
: : 송신측에서는 재전송요청을 받으면
: : 해당Packet의 Data+CheckSum+Packet번호 를 송신합니다.
: : Packet번호는 2Byte입니다.
: :
: :
: : 즉 일단 file을 모두 전송한후에
: : 저쪽에서 error가 있다는 부분만 다시 전송해주는 구조입니다.
: :
: : [한번에 전송되는 data구조 1,2,3]
: : 1 - FileName+FileSize ==> 맨처음에 file에 대한 정보를 전송한다.
: : 2 - Data+CheckSum ==> 다음. 일정크기+1Byte =1025Byte 씩 data를 전송합니다.... File끝까지
: : .
: : .
: : 3 - Data+CheckSum+Packet번호 ==>마지막으로 일정크기+1Byte+2Byte=1027Byte error packet을 전송합니다.
: :
: : 전송종료는 data를 모두 전송후에 일정시간(2초)이상 error패킷에 대해 재전송 요청이 없으면
: : 전송을 마무리하구요
: :
: : 수신측에서는 Data를 완벽하게 수신했거나 에러packet이 있을경우 송신측에서 일정시간 전송해주시 않으면
: : 그냥 수신실패한것으로 마무리 합니다.
: :
: :
: : 문제점과 의문나는점은?
: :
: : 1) 재전송요청한 packet에서 계속반복해서 Error가 나는경우가 있구요
: : 2) 처음 file전송시(2번)에는 data에 대한 packet번호를 수신측에서 차례대로 수신한다고 생각하고
: : 함께 전송하지 않습니다.--> 그래도 되는지...?
: : 3) 송신측에서 전송중에 재전송요청을 받았을때.. 그 부분부터 다시보내는것이 좋을런지...?
: : 4) 보통 메신져(MSN이나 NateOn 같은데)에서는 어떻게 하는지?
: : 5) CheckSum 만드는 더좋은 방법이 있으면 소개좀 부탁드립니다.
: : 6) 마지막을 ZModem처음 전송되는 Packet의 크기를 가변적으로 하려면 어떻게 해야하죠?
: : 에러가 없으면 점점 전송되는 packet의 크기가 커지는것으로 알고잇는데.... (너무 막연한 질문인가?)
: :
: : 목표
: : 가능한한 최대한 빠르게 파일이 전송 되어야합니다.
: : 그럴러면 전송되는 data에 Header가 적어야겠죠(반드시 그렇지는 않겠지만)
: : 그리고 당연히 수신file에 1Byte라도 error는 없어야겠구요?
: : 마지막으로 수신측에서도 Acknowledge같은것도 최대한 적게 보내야 합니다.
: : XMODEM이나 YMODEM같은경우는 한번수신할때만다 Acknowledge를 보내는것으로 알고있습니다.(맞나?)
: :
: : 참고로 이 파일전송 부분은 직접구현해야합니다.
: : FTP나 다른 컴포넌트를 이용할수 없습니다.
|