|
임문환 님이 쓰신 글 :
:
: 안녕하세요?
:
: TServerSocket, TClientSocket둘 모두 stNonBlocking으로 하구요.
: TThread를 별도로 사용하지는 않았습니다.
:
: void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender,
: TCustomWinSocket *Socket)
: {
: UMessageBuffer messageBuffer; //구조체들의 공용체 512 Byte
: Socket->ReceiveBuf((void*)(&messageBuffer),sizeof(UMessageBuffer));
:
: 1: Socket->SendBuf((void*)(&messageBuffer),sizeof(UMessageBuffer));
: 2: Socket->SendBuf((void*)(&messageBuffer),sizeof(UMessageBuffer));
: }
:
: 이렇게 두 번을 같은 클라이언트에 거의 동시에 보내게 되면
: 클라이언트의 OnRead 이벤트는 두 번 모두 발생하는데
: 두 번째 보낸 것을 클라이언트에서 제대로 받질 못합니다.
:
: 한편, 2에서 Socket를 다른 클라이언트로 하면 두 클라이언트 모두 제대로 받더군요.
:
: 그리고 한 클라이언트에서
: 1: ClientSocket1->SendBuf((void*)(&messageBuffer),sizeof(UMessageBuffer));
: 2: ClientSocket1->SendBuf((void*)(&messageBuffer),sizeof(UMessageBuffer));
: 위와 같이 서버에 연속해서 두 번 보내면 서버는 둘 모두 제대로 받더군요.
:
: 서버에서 동일한 클라이언트에 동시에 두 번 메시지를 보낼 때 왜 클라이언트에서
: 두 번째 메시지를 제대로 받지 못하는지요?
: 그리고 어떻게 하면 이를 해결할 수 있을까요?
:
: 여러분의 도움을 구합니다.
:
:
: 감사합니다.
:
:
안녕하세요. 제임스 입니다.
작은 도움이 될까해서 적는건데요.
우선은 비동기 소켓이 뭔가에 대한 이해가 좀 필요할 거 같습니다.
비동기 소켓, 즉 TServerSocket과 TClientSocket엣 ServerType = stNonBlocking,
ClientType = ctNonBlocking이라고 설정은 비동기소켓을 쓰겠다는 뜻입니다.
소켓은 다양한 수준의 조합으로 인한 처리 방법이 있는데 , 간단히 비동기와 동기로 구분하자면
비동기는 네트웍 카드의 버퍼에 packet 이 도착하였을때 메세지 또는 event가 발생하는 것입니다.
따라서 정확히 얼마간의 데이타가 들어왔는지 모르며 이를 위해서는 ioctl 또는 readlength()라는
컴포넌트의 함수를 사용해야하죠.
예를 들자면, A라는 클라이언트가 B라는 서버로 512바이트를 보낸다고 합시다.
A와 B가 지극히 정상적으로 작동한다면 아무런 문제 없이 512바이트를 한꺼번에 보내며,한꺼번에
받을 것입니다.
하지만 A가 512바이트를 보내고 또 보내고 연달아서 2번을 B서버로 보낸다고 합시다.
여기서 A는 분명히 2번 메세지를 send했습니다. 그러나 B에서는 메세지가 2번 받아질때도 있고
한번 받아질때도 있습니다. 이유는 비동기는 네트웍에 데이타가 도착할때 event나 메세지가 발생
해서 처리하는데 A가 두번 보낸 1024바이트를 연결된 데이타로 인식하고 읽어드릴수도 있다는것이죠.
따라서 readevent함수에서 가끔씩 1024가 나올때가 있고 512가 나올때도 있을 겁니다.
이를 해결하기위해서는 Queue를 만들어서 받은 데이타를 저장하고 거기서 필요한 만큼 쓰며
나머지는 남겨서 다음에 도착한 데이터랑 붙여서 다시 데이타의 의미를 파악하고 처리하는식이죠.
비동기 소켓은 동기 소켓보다 다루기 힘들지만 서버가 제대로 된 서버가 되기위해서는 비동기
소켓을 사용해야할것입니다.
|