Overlapped I/O 모델

2015. 5. 17. 01:27프로그래밍/서버

728x90
728x90

특징

- 비동기 데이터 송수신을 할 수 있다.

- 소켓 내부 버퍼를 사용하지 않고 직접 TCP 전송 버퍼에서 데이터를 본재고 받을 수 있다.


비동기 송수신, WSAAsyncSelect Model vs Overlapped I/O Model 

WSAAsyncSelect 

데이터를 송수신 하면서 다른 일을 할 수 있다고 생각할 수 있지만 

윈도우 메시지가 왔을 때 send(), recv()를 통해 데이터를 송수신 한다.

프로그래머가 직접 데이터를 송수신 하겠다는 의미이다.


Overlapped I/O

커널에 데이터를 송수신 하겠다고 요청을 하고나서 따로 데이터를 송수신을 할 필요가 없다.

WSASend()나 WSARecv()를 이용해 Overlapped I/O로 데이터를 송수신 하는 것이다.

한 마디로 커널이 직접 데이터를 송수신하고 그 결과를 프로그래머에게 알려주는 것이다.


소켓 내부 버퍼를 사용하지 않는 것

기본적으로 설정되는 특징은 아니다. 소켓 옵션 함수를 이용해 소켓 내부 버퍼를 0으로 만들어 주어야 가능하다.

소켓 전송 버퍼가 0이면 TCP에 직접 전송한다. 메모리 복사를 한 번 줄여주는 것이 엄청난 성능 향상!


소켓 전송 버퍼를 0으로 했을 때 주의해야 할 점

TCP 수신 버퍼에서 바로 가져올 수 있도록 충분한 수의 Overlapped I/O 호출을 미리 해야 한다.

- Overlapped I/O 호출을 미리 하지 않으면 TCP 수신 버퍼로 들어오는 데이터양이 사용자 버퍼로

읽어 들이는 양보다 많아져 TCP 수신 버퍼가 금방 다 차서 상대방에 데이터를 보내지 못하는 경우가 생긴다.


TCP 송신 버퍼에서 내보내는 데이터양보다 사용자 TCP 송신 버퍼로 보내는 데이터양이 많아

사용자 버퍼에서 TCP 송신 버퍼로 복사되기 전까지 그 사용자 버퍼를 사용할 수 없다는 것이다.


Overlapped I/O 사용시 주의 점

데이터를 보낼 때는 데이터 송신 작업이 완료될 때까지 데이터가 들어있는 사용자 버퍼를 삭제해선 안된다.


WSASend, WSARecv 함수 분석

인자

SOCKET s - 데이터를 보낼 연결된 소켓

LPWSABUF lpBuffer - WSABUF 구조체 변수에 보낼 데이터의 크기와 데이터를 채우고 변수의 포인터를 인자로 넣는다.

DWORD dwBufferCount - 버퍼의 개수를 넣는다. 두 번째 인자로 넣은 WSABUF 구조체의 배열 개수를 넣으면 된다.

DWORD flag - send(), recv()와 동일

LPWORD lpNumberOfBytesSent

LPWSAOVERLAPPED lpOverlapped

- 가장 중요한 역할을 한다.

WSAOVERLAPPED 구조체 분석

DWORD Internal

DWORD InternalHigh

DWORD Offset

DWORD OffsetHigh

내부적으로 사용하는 변수들. 0으로 초기화. <- 이건 나중에 좀 더 알아보자..

WSAEVENT hEvent

- 이벤트 객체의 핸들로써 Overlapped I/O 요청이 완료되었다는 것을 알려주는 역할을 한다.

LPWSAOVERLAPPED _COMPLETION_ROUTINE lpCompletionROUTINE

- 완료 루틴에 대한 포인터를 받는다.

완료 루틴이란? Overlapped I/O가 완료되면 호출되는 콜백 함수를 말한다.


함수의 반환 값이 0이면 Overlapped I/O 요청이 즉시 완료 되어 함수 호출이 성공했다는 것을 의미.

0이 아니라면 GetLastError() 함수를 이용하면 WSA_IO_PENDING 인지 확인한다.

에러 코드가 이것이라면 요청한 Overlkapped I/O가 즉시 처리 되지 않고 나중에 처리 된다는 의미!!

WSA_IO_PENDDING이 아니라면 함수 호출에 실패한 것.


Scatter-Gatter I/O

우리말로 풀면 분배-집합 입출력. WSASend() 함수를 이용하여 여러 개의 버퍼를 하나의 패킷으로 묶어 보내고

받는 쪽에선 WSARecv() 함수를 이용하여 하나의 패킷으로 받아서 다시 여러 개의 버퍼로 나눌 수 있다.

일반적으로 고정되고 형식화된 데이터를 송수신 하는 프로그램에서는 유용하지만 게임 서버에서는 거의 쓰지 않는다.


728x90
반응형

'프로그래밍 > 서버' 카테고리의 다른 글

동기화  (0) 2015.07.23
Thread  (0) 2015.07.23
Blocking vs Non-Blocking  (0) 2015.07.12
[서버] 데드 레커닝(Dead Reckoning)  (1) 2015.05.23
IOCP 정리  (0) 2015.05.14
TCP/IP 프로토콜 개요  (1) 2015.04.27
메모리 풀(Memory Pool)  (0) 2015.03.18