2014년 5월 10일
IOCP의 Recv 처리 부분을 보면 WSARecv 함수를 통해 패킷 수신 대기 상태에서
패킷 수신 신호가 오면 GetQueuedCompletionStatus함수가 수행되어 패킷을 받을 수 있게된다.
이 때 GetQueuedCompletionStatus 함수의 두번째 인자로 부터 받은 패킷의 사이즈를 확인 할 수가 있는데
이 사이즈는 WSARecv 함수와 연관이 되어 있다.
WSARecv함수의 두번째 인자 WSABUF를 통해 GetQueuedCompletionStatus 함수에서 수신 받을 수 있는 패킷의 한도가 결정된다. 이와 같은 방식을 활용하기 위해 조금 복잡한 처리를 거치게 된다. 물론 사이즈를 넉넉히 잡고 해당 사이즈 안에서만 패킷을 송수신한다면 편하게 개발할 수는 있지만 많은 수의 유저를 받을 경우에는 메모리 낭비가 심하게 될 것이다.
확실히 눈으로 보기 위해 테스트를 해봤다.
우선 WSARecv에서 WSABUF의 len 값을 1024로 맞추고, 이보다 큰 사이즈의 패킷을 전송했다.
▲ 클라이언트에서 전송한 패킷 사이즈는 1568Byte
서버에서 받은 패킷의 한도는 1024 이므로 이보다 큰 패킷은 두번으로 나뉘어 수신된다.
그래서 처음 받은 패킷의 사이즈는 1024Byte가 된다.
▲ 첫번째 받은 패킷 사이즈
곧이어 받게되는 패킷은 나머지 패킷으로 544Byte
▲ 두번째 받은 패킷 사이즈
이번에는 WSABUF의 len 사이즈를 4098Byte로 늘린 후 같은 패킷을 전송했다.
이 때는 패킷을 수신하기 충분하므로 한번에 패킷을 수신하게 된다.
▲ 사이즈 조정 후 받은 패킷 사이즈
이와 같이 WSARecv에서 지정된 사이즈보다 큰 사이즈의 패킷을 처리하기 위해, 그리고 패킷을 좀 더 효율적으로 수신받기 위한 처리가 필요하다. 패킷 사이즈에 따라 Buffer를 조절하기 위해 처음에는 기본값으로 사이즈를 설정해주고 큰 사이즈의 패킷이 오게되면 해당 Buffer의 사이즈를 늘려주는 처리를 해주었다.
Offset : 수신된 패킷을 읽은 위치 Len : 수신 받은 패킷의 사이즈 TotalSize : 패킷의 총 사이즈 |
클라이언트와 사전에 패킷에 대한 총 사이즈를 패킷에 넣어 줄 것을 약속한 후 먼저 패킷의 총 사이즈를 읽는다.
총 사이즈보다 수신 받은 패킷의 사이즈가 작을 경우에는 수신 받을 패킷이 더 있다는 의미이므로 Offset과 Len 값을 조절하지 않은 채로 수신을 더 받는다. TotalSize가 Buffer의 사이즈를 초과 할 경우에는 Buffer 사이즈를 늘려 준 후 Len 값이 TotalSize와 같아질 때까지 수신을 받은 후 패킷에 대한 처리를 해 준다. Buffer 사이즈를 늘릴 수 있는 한도를 넉넉히 잡아 비정상적인 패킷을 제외한 패킷을 모두 수용할 수 있게끔 하였다.
패킷에 대한 처리를 완료한 후에는 Offset값과 Len값을 조정(Len 값은 읽은 만큼 빼주고, Offset값은 0으로 초기화)하여 다음 패킷을 받을 수 있도록 했다.
'Programming > C++' 카테고리의 다른 글
[C++] make_pair를 이용하여 데이터 관리 (0) | 2015.07.13 |
---|---|
[C++] TCP/IP 의 window size에 대비한 처리 (0) | 2015.05.25 |
[C++] inet_addr, htons 함수 (1) | 2013.04.11 |
[C++] static const에 대한 고찰 (0) | 2013.04.11 |
[C++] strtok 함수 (0) | 2013.04.11 |
댓글