|
해결 했습니다.-_-
if(pStream->WaitForData(15000)) ///이 부분을 추가 했더니 문제 없이 돌아 갑니다.-_-''
{
try
{
BufferSize = pStream->Read(tmpBuffer, (HeaderSize - NowLength)) ;
}
catch(Exception &E)
{
ClientSocket->Close();
break ;
}
}
원인은 찾아서 해결은 했는데...정확하게 왜 오류가 났었는지는 모르겠네요
WaitForData 라는게 데이타가 들어오기를 기다리는 함수 인데...
이게 없다고 오류가 난다는게...좀....이해가 안갑니다...
아시는 분 계시면 시원하게 설명을 부탁드립니다.
근데....또 하나의 문제가 있습니다....
"Read error 64, 지정된 네트워크 이름을 더 이상 사용할 수 없습니다"
이 오류가 납니다.
이 오류에 대해 찾아 보았더니 클라이언트의 비 정상적인 종료로 인한 오류 라고 하더군요....
근데 문제는 넘 자주 난다는 겁니다.
받는 데이타의 10% 가량이 위 와 같은 오류를 냅니다.
머 클라이언트 쪽 사양이 IP공유기를 사용하기 때문에 네트웍 불안정으로 그런다라고 할 수 있지만...
그게 모든 원인은 아닌거 같기도 하고 하네요...
혹 제가 모르고 있는 위 오류에 대해 알려주세요...
고수님들께 부탁합니다.(__)
mani 님이 쓰신 글 :
: 클라이언트가 파일을 보내면 서버가 받아서 저장하는 프로그램을 만들고 있습니다.
: 서로 주고 받는 것은 구조체 형태로 받고 있고요
: 구조는
: #pragma pack(1)
: typedef struct {
: unsigned long Length ; //Packet 총 길이에서 Packet Header 길이 제외
: unsigned long File_TotLength ;//요청한 파일의 total length
: unsigned long SentLength ; //현재까지 수신한 파일의 length
:
: } SendHeader ;
:
: #pragma pack(1)
: typedef struct {
: char FileStream[4096] ; //MP3 Stream Data
:
: } SendFile ;
:
: 이렇게 헤더와 바디를 따로 구분해서 보내고 받습니다.
:
: 근데 수신을 받다 보면 패킷이 이상하게 들어 옵니다.
: 헤더가 안들어 오고 바로 바디가 들어 오네요....
:
: 보내는 로직
: SendHeader sSendHeader ;
: SendFile sSendFile ;
: filestream = new TFileStream(Filename ,fmOpenRead) ;
:
: filestream->Seek( 0 , soFromBeginning) ;
: FileLength = filestream->Size ;
: Cnt = (FileLength / 4096) + 1 ;
:
: for (int Loop1 = 0 ; Loop1 < Cnt ; Loop1 ++)
: {
: if (SendGo == false)
: {
: ClientSocket1->Active = false ;
: break ;
: }
: memset(&sSendHeader , 0 , sizeof(sSendHeader)) ;
:
: if (FileLength - (Loop1 * 4096) > 4096)
: SendLength = 4096 ;
: else
: SendLength = FileLength - (Loop1 * 4096) ;
:
: filestream->Read(&sSendFile.FileStream ,SendLength ) ;
: sSendMP3Header.Length = SendLength ;
: sSendMP3Header.File_TotLength = FileLength ;
: sSendMP3Header.SentLength = ((Loop1 * 4096) +SendLength) ;
: ClientSocket1->Socket->SendBuf(&sSendHeader , sizeof(sSendHeader)) ;
: ClientSocket1->Socket->SendBuf(&sSendFile , sizeof(sSendFile)) ;
:
: if (Loop1 != Cnt-1)
: filestream->Seek(0 , soFromCurrent) ;
: Sleep(1) ;
: }
: }
:
: 클라이언트에서 이렇게 보냅니다.
:
: 서버에서는 파일 길이를 다 받을 때까지 루프를 돌면서 헤더와 바디를 구분합니다.
: 클라이언트가 3개 정도 붙으면 문제가 안되는데 4개 이상붙으면 헤더값이 이상한게 들어 오는 넘들이 있습니다.
: 아래 소스 보시면 아시겠지만
:
: if (RcvLength <= 0 || RcvLength > 4096)
: {
: SocketWrite_Log("[패킷 오류]" , 1) ; // RcvLength 가 4096 이상이 될 수가 없슴
: RecieveEnd = true ;
: break ;
: }
:
: RcvLength 는 4096이 넘을 수 없습니다.
: 근데 패킷을 받다보면 터무니 없는 값(억단위가 넘는 값이죠..-_-)이 들어 옵니다.
: 그래서 확인한 결과 바디에 와야 할 내용이 헤더로 들어 오고 있다는 것을 알게 되었습니다.
:
: 근데 지금까지 받은 바디 사이즈 그리고 전체 패킷 사이즈를 기록해 봤는데
: 패킷오류가 나는 시점에서도 사이즈는 정상 입니다.
: 예를 들면 바디사이즈는 4096으로 나누면 값이 딱 떨어 집니다.
: 전체 패킷 값도 4108 로 나누면 나머지가 12가 남습니다
: 여기서 12는 헤더 정보를 받아 온 후이기 때문에 12가 남는것은 당연한 것이구요...
:
: 혹시 제가 발견하지 못한 오류나 아니면 생각지도 못했더 로직상의 오류가 있는지 모르겠네요...
:
: 며칠째 이거 가지고 씨름하다가 이렇게 글을 올립니다.
:
: 고수님들의 도움 부탁 드립니다.
:
: 서버에서는 아래와 같이 받아 옵니다.
:
: String sFilename ;
: sFilename = "c:\a.txt" ;
:
: if (!FileExists(sFilename))
: sFileHandle = FileCreate(sFilename) ;
:
: RecieveEnd = false ;
: SocketWrite_Log("[수신시작" , 1) ;
: RcvYn = "N" ;
:
: SendFile sSendFile ;
: SendHeader sSendHeader ;
:
: int fFileSize = 0 ;
: int NowLength ;
: int TotalRcvPackLen = 0 ;
: char *tmpBuffer ;
: tmpBuffer = new char[sizeof(sSendHeader )+1] ;
: char tmpBuffer3[sizeof(sSendHeader )] ;
: char tmpBuffer4[sizeof(sSendFile)] ;
: char *tmpBuffer2 ;
: tmpBuffer2 = new char[sizeof(sSendFile)+1] ;
:
: while (!RecieveEnd)
: {
: try
: {
: memset(tmpBuffer3, 0x0, 12);
: memset(&sSendHeader , 0x0 , 12) ;
: memset(tmpBuffer , 0x0 , 13) ;
: NowLength = 0 ;
: LoopCnt = 1 ;
: try
: {
: while ( NowLength < sizeof(sSendHeader ))
: {
: try
: {
: BufferSize = pStream->Read(tmpBuffer, (sizeof(sSendHeader ) - NowLength)) ;
: }
: catch(Exception &E)
: {
: ClientSocket->Close();
: RecieveEnd = true ;
: break ;
: }
:
: if( BufferSize == 0) // 입력된 값이 없으면 종료
: {
: if (LoopCnt == 1000)
: {
: ClientSocket->Close();
: RecieveEnd = true ;
: break ;
: }
: LoopCnt+= 1 ;
:
: try
: {
: WaitForSingleObject((HANDLE)Handle , 10) ; //약간의 Sleep을 주기 위해 사용
: }
: catch(...)
: {
: ::Sleep(10) ;
: }
: continue ;
: } else
: {
:
: memcpy((void *)&tmpBuffer3[NowLength] , (void *)&tmpBuffer[0] , BufferSize) ;
: NowLength = NowLength + BufferSize ;
: if ( NowLength == 12)
: break ;
: try
: {
: WaitForSingleObject((HANDLE)Handle , 2) ;
: }
: catch(...)
: {}
: }
:
: }
: if (RecieveEnd)
: {
: break ;
: }
: TotalRcvPackLen = TotalRcvPackLen + 12 ;
: Move(tmpBuffer3 , &sSendHeader , 12) ;
:
: SaveFileLenth = sSendHeader.SentLength ;
: RcvLength = sSendHeader.Length ;
: TotalLength = sSendHeader.File_TotLength ;
:
: if (RcvLength <= 0 || RcvLength > 4096)
: {
: SocketWrite_Log("[패킷 오류]" , 1) ; // RcvLength 가 4096 이상이 될 수가 없슴
: RecieveEnd = true ;
: break ;
: }
: }
: catch(Exception &E)
: {
: RecieveEnd = true ;
: break ;
: }
:
: NowLength = 0 ;
: LoopCnt = 1 ;
: memset(&sSendFile , 0x0 , sizeof(sSendFile)) ;
: memset(tmpBuffer4 , 0x0 , sizeof(sSendFile)) ;
: memset(tmpBuffer2, 0x0, sizeof(sSendFile)+1);
: try
: {
: while ( NowLength < RcvLength)
: {
: try
: {
: BufferSize = pStream->Read(tmpBuffer2, RcvLength - NowLength) ;
: }
: catch(Exception &E)
: {
: ClientSocket->Close();
: RecieveEnd = true ;
: break ;
: }
: if ( BufferSize == 0)
: {
: if (LoopCnt == 1000)
: {
: ClientSocket->Close();
: RecieveEnd = true ;
: break ;
: }
: LoopCnt+= 1 ;
:
: try
: {
: WaitForSingleObject((HANDLE)Handle , 10) ;
: }
: catch(...)
: {
: ::Sleep(10) ;
: }
: continue ;
:
: }
: else
: {
:
: memcpy((void *)&tmpBuffer4[NowLength] , (void *)&tmpBuffer2[0] , BufferSize) ;
: fFileSize = fFileSize + BufferSize ;
: NowLength = NowLength + BufferSize ;
: if ( NowLength == RcvLength)
: break ;
: //::Sleep(10) ;
: try
: {
: WaitForSingleObject((HANDLE)Handle , 1) ;
: }
: catch(...)
: {}
: }
: }
: }
: catch(Exception &E)
: {
: RecieveEnd = true ;
: break ;
: }
: TotalRcvPackLen = TotalRcvPackLen + NowLength ;
: Move(tmpBuffer4 , &sSendFile , NowLength) ;
: try
: {
: FileSeek(sFileHandle,0,2);
: FileWrite(sFileHandle, sSendFile.FileStream , RcvLength ) ;
: }
: catch(Exception &E)
: {
: RecieveEnd = true ;
: }
:
: if (FileLength == fFileSize )
: {
: RecieveEnd = true ;
: }
: try
: {
: WaitForSingleObject((HANDLE)Handle , 10) ;
: }
: catch(...)
: {
: ::Sleep(10) ;
: }
:
: }
: catch ( Exception &except )
: {
: ClientSocket->Close();
: ErrorCode = "4" ;
: RecieveEnd = true ;
: }
: }
: FileClose(sFileHandle);
|