|
감사합니다. 님 말씀처럼 테스트를 해보니 2번 출력이 되네요.. ReceiveLength()를 사용해 실제값이 0인경우 바루
리턴을 시키니.. 잘 되네요... ^^ 다시한번 감사 드립니다.. 그럼 즐거운 하루 보내세요....^^
ㅇ 님이 쓰신 글 :
: 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;
: }
|