|
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;
}
|