|
클라이언트가 파일을 보내면 서버가 받아서 저장하는 프로그램을 만들고 있습니다.
서로 주고 받는 것은 구조체 형태로 받고 있고요
구조는
#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);
|