C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[36943] Re:^^;
이점한 [redyouth] 1853 읽음    2004-08-23 18:55
예전의 ZMODEM이나 YMODEM, XMODEM, 커밋(?) 등은 TCP/IP라는 프로토콜 레이어단에서 작동 하던게 아니죠.

저도 지식이 미천하나마 제가 알고 있는 지식에서 UDP가 아닌 TCP/IP구조에서는 패킷 손실이나 패킷 전송 자체를

안정성을 보장 한다는 전제에서 만든 말그대로 테스트 프로그램입니다. 그래서 큰마음 먹고 올린다고 했죠 ^^;

사실은 님의 말씀처럼 좀 더 안전성이 보장된 소스를 강좌 형식으로 올리고 싶었지만 님께서 다른 방식의 파일전송을

원하시기에 이런류의 방식도 있다라고 제시 하고 싶은 마음에 좀 완성도가 떨어진 소스를 보내준 것 같네요. 하지만

나름대로 스레드블럭킹을 소개 한 것같아 조금은 낫지만 님의 말씀대로 패리티체크 개념을 넣으실려면 소스를 많이

변형 해야겠죠. 현재 스레드블럭킹은 데이타전송하는 역활만 하는데 그 패킷에 포함해서 처리 하려면

TWinSocketStream 에서 Read 해서 처리를 해야 할 것 같네요. 저는 단지 스레드블럭킹의 소개 정도로 생각 해주시면

님이 원하시는 답이 될것이라는 생각이였습니다. 주저리 주저리 말만 많이 적었는데 시간 나면 다시 한 번 정리 해서

올리도록 하죠. 다시 한 번 말씀드리지만 큰맘 먹었다는 얘기는 인심 크게 쓰겠다는 뜻이 아니고 제대로 준비는 덜 되었

지만 도움이 될거라는 생각에 적은것입니다.  ^^;

굳이 덧붙인다면 저 예제 소스에서 조금 응용해서 현재도 실무에 잘쓰고 있답니다. 다시 한 번 시간이 허락 한다면

여러가지 보완된 소스를 정리 좀 해서 다시 올려 드릴께요. 그럼 즐코~ 하세요!


장성호 님이 쓰신 글 :
: 감사합니다
: 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나 다른 컴포넌트를 이용할수 없습니다.

+ -

관련 글 리스트
36935 소켓으로 파일전송시하는데... 좋은 알고리즘 좀 가르쳐 주세요 장성호 2997 2004/08/23
36940     빌더 5로 컨버젼 해주시면 안될까요.-인디와 다른점은.. 하안인 1253 2004/08/23
36942         Re: 컨버젼 .. 간단하니까 직접하셔도.. 될듯.. 장성호 1217 2004/08/23
36941         Indy 컴포넌트와 다른점은 무엇인가요 하안인 1319 2004/08/23
36944             Re:Indy 컴포넌트와 다른점은 무엇인가요 이점한 1605 2004/08/23
36945                 감사합니다. 하안인 880 2004/08/24
36937         감사합니다. 그런데.... Packet에 Error라 발생할때는 고려가 되어있지 않네요 장성호 1475 2004/08/23
36943             Re:^^; 이점한 1853 2004/08/23
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.