원본 : http://www.debuglab.com/knowledge/socketreceive.html
1.요약
CSocket에서 Receive하는 몇가지 방법을 알아 본다.
2.본문
int CXXXSocket::Receive(LPVOID lpBuf, int nBufLen, int nFlags)
{
int nRead;
int nLeft = nBufLen;
PBYTE pBuf = (PBYTE)lpBuf;
while(nLeft > 0)
{
nRead = CSocket::Receive(pBuf, nLeft);
if (nRead == SOCKET_ERROR)
{
return nRead;
}
else
if (nRead == 0)
{
return nBufLen - nLeft;
}
nLeft -= nRead;
pBuf += nRead;
}
return nBufLen - nLeft;
}
위의 방법은 winsock1.0사용시 가장 확실하게 Receive버퍼를 비우는 방법입니다. 버퍼에 남아있는 내용이 없을때까지 while문을 돌면서 Receive를 하기 때문이죠. 하지만 보내준 Packet을 한번 받지 못하는 문제를 해결하는 다른 방법도 있죠.
① 버퍼에 남아있는 양을 미리 알아내고 그 양만큼 한번에 받는 방법.
② Receive한 직후 버퍼에 데이터가 남아있는지 검사하여 받는 방법.
①의 방법을 사용한다면 Receive해보는 것보다 부하나 속도면에서 효율 있겠죠. Receive 버퍼에 남아있는 데이터의 양을 알아내는 함수는 ioctlsocket을 이용합니다. CSocket에서는 CAsyncSocket::IOCtl()이죠.
CSocket style : IOCtl(FIOREAD, &dwReadSupposed); BSD style : ioctlsocket(sock, FIOREAD, &dwReadSupposed);
만일 Send 버퍼에 남아있는 데이터의 크기를 알고 싶다면 FIOREAD대신에 FIOWRITE를 쓰면 되겠죠.
ioctlsocket를 이용해 받을 양을 미리 예측하고 그만큼 받으면 한번에 받을수 있을겁니다.
②의 방법은 GetLastError()를 이용하여 소켓이 WOULDBLOCK상태인지 확인하는 것입니다. 소켓 수신계층에서 WOULDBLOCK이란 더이상 읽어들일 데이터가 없는 상태를 의미합니다.
if( GetLastError() != WOULDBLOCK) // 더 받는다.
정리를 하자면 ①의 과정을 거쳐서 받을 데이터의 양을 미리 예상하여 한번에 받기 작업을 하고 ②과정을 거쳐 확인 사살(?)을 한다면 가장 확실한 방법이 되겠죠.
3.예제
① IOCtl(FIOREAD, &dwReadSupposed);
② Receive(Buffer, dwReadSupposed, 0);
③ if( GetLastError() != WOULDBLOCK)
// 더 받기 ※ 소켓 수신계층에 남아있는 데이터를 어떤방법을 쓰던간에 한번에 읽는게 좋습니다. 왜냐하면 TCP의 경우 송신측과 수신측이 밀접하게 연관 되어 있어서 받는 쪽에서 Receive를 빨리 해주면 해줄수록 전송속도가 올라가기 때문입니다. 만일 Receive를 빨리 해주지 못하면 송식측은 WOULDBLOCK상태에 빠지는데 이는 더이상 데이터를 보낼 수 없음을 의미합니다.
4.참고
마이크로소프트웨어, 데크니컬 컬럼.
- 2001.08.13 Smile Seo -
- libpcap을 이용한 포트스캐닝 검사 (2)2007/05/11
- 네트워크관련 정보 얻기 (0)2007/05/11
- Socket에서 완벽한 Receive처리 (0)2007/03/02
- 네트워크 프로그래밍의 원리 이해 - 5 (0)2005/05/29
- 네트워크 프로그래밍의 원리 이해 - 4 (0)2005/05/29

수안이의 컴퓨터 연구실



Leave your greetings.