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
[43595] Re:TServer Socket에서 ReceiveBuf()관련입니다.
[] 2114 읽음    2006-02-08 01:18
pili 님이 쓰신 글 :
: 먼저 읽어주셔서 감사합니다.
:
: 다름이 아니라 TClientSocket과 TServerSocket을 이용해 구조체를 주고 받습니다.
:
: 문제는 아래와 같이 작성해서 돌려보면 결과값이 2번씩 출력되네요..ㅜ.ㅜ..
:
: 문제될꼐 없는 것 같은데.. 혹시 뭐가 잘 못된게 있나해서 이렇게 글을 남김니다. 그럼 즐거운 하루 보내세요.
:
: 코드는 다음과 같습니다.
:
: ---공 통---
: #define     sDeleteMessageLen       sizeof(DELETEMESSAGE)
: typedef struct sDeleteMessage
: {
:     unsigned char szFlag;
:     char szItemGuid[32];
:     char szuName[32];
: }DELETEMESSAGE, *PDELETEMESSAGE;
:
: ---클라이언트---
: 전송부분
:         DELETEMESSAGE* pDeleteMessage = new DELETEMESSAGE;
:         pDeleteMessage ->szFlag = MSGID_DELETEMESSAGE;
:         strcpy(pDeleteMessage ->szuName, "Test");
:         strcpy(pDeleteMessage ->szItemGuid, "TestGuid");
:
:         csock->Socket->SendBuf((char*)pDeleteMessage , sDeleteMessageLen );
:
: -- 서버부분 --
: 서버부분 헤더에 구조체에 대해 공용체로 선언해 놓았습니다.
: typedef union
: {
:     unsigned char   uType;
:     DELETEMESSAGE   stDeleteMessage;
:     SEARCHITEMREQ   stSearchItemReq;
: } RCVCLIENTDATA;
:
: 받는 부분--
: RCVCLIENTDATA pRcvClientData;
: Socket->ReceiveBuf((char*)&pRcvClientData, 1);  <-- 공용체의 uType을 확인 한 후 switch를 수행합니다.
:
: switch(pRcvClientData.uType)
:         {
:         case MSGID_DELETEMESSAGE:
:             Socket->ReceiveBuf(((char*)&pRcvClientData) + 1, sDeleteMessageLen );
:             Memo1->Lines->Add(pRcvClientData.stSearchItemPon.szmFlag);
:             Memo1->Lines->Add(pRcvClientData.stSearchItemPon.szmFlag);
:             Memo1->Lines->Add(pRcvClientData.stSearchItemPon.szmFlag);
:             break;
:         case ....
:         case ....
:             break;
:         default:
:             break;
:         }

클라이어트가 한 번의 SendBuf 호출로 보낸 데이터에 대해 서버에서는 OnClientRead 이벤트 핸들러가 여러번 호출될 수 있습니다. 예를 들면, 클라이언트가 보낸 데이터를 앞에서부터 셋으로 나누어 세번 호출할 수 있습니다.

한편, 함수 내부의 비정적변수들은 스택에 생성이 되고 return 시에는 해당 스택영역을 반납하게 되며 다른 함수 호출로 그 값이 변하게 되는게 보통인데 동일한 함수를 동일한 매개변수로 연속하여 호출하면 이전에 스택에 생성된 변수들의 값이 그대로 살아 있게 됩니다.

지금 상황은 위의 두 가지가 동시에(복합적으로) 발생한 것입니다.

이 문제를 해결하려면, 아래와 같이 ReceiveLength()로 조사하여 실제 읽어들일 데이터가 없으면 그냥 return하면 됩니다.

한편, 정말 두 번 이상 호출되고 사용했던 스택영역을 그대로 다시 사용하여 값이 살아 있게 되는 것인지 테스트해보려면 위 검사를 하지 말고 함수 끝부분에서 strcpy(pRcvClientData.stDeleteMessage.szuName, "정말 그렇네");를 해보세요.
그러면, 두번째 이후 호출될 때 클라이언트가 보낸 내용과 달리 "정말 그렇네"가 출력되는 것을 확인할 수 있을 것입니다.


그리고, ReceiveBuf의 반환값을 확인하세요.
만약, 받고자 하는 양보다 적다면 다 받을 때까지 반복해서 받아야 합니다.

Memo1->Lines->Add(String("Read: ")+Socket->RemoteAddress+":"+Socket->RemotePort);
if(Socket->ReceiveLength()==0) return;

RCVCLIENTDATA pRcvClientData;
Socket->ReceiveBuf((char*)&pRcvClientData, 1);  <-- 공용체의 uType을 확인 한 후 switch를 수행합니다.
switch(pRcvClientData.uType)
{
  case MSGID_DELETEMESSAGE:
     Socket->ReceiveBuf(((char*)&pRcvClientData) + 1, sDeleteMessageLen );
     Memo1->Lines->Add(pRcvClientData.stDeleteMessage.szFlag);
     Memo1->Lines->Add(pRcvClientData.stDeleteMessage.szItemGuid);
     Memo1->Lines->Add(pRcvClientData.stDeleteMessage.szuName);
     break;
  default:
     break;
}

+ -

관련 글 리스트
43592 TServer Socket에서 ReceiveBuf()관련입니다. pili 1256 2006/02/07
43595     Re:TServer Socket에서 ReceiveBuf()관련입니다. 2114 2006/02/08
43596         님 감사합니다.. ^^ 해결되었네요.. pili 988 2006/02/08
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.