글 작성자: Sowhat_93

1. closesocket 이후에 OS는 closesocket 의 인자로 전달했던

것과 같은 값을 가지는 핸들을 리턴할 수 있다.

 

closesocket은 TCP 단에서의 연결종료 루틴의 수행 뿐 아니라

핸들을 반납하는 역할 또한 수행한다.

 

closesocket이후 OS는 같은 핸들을 반환할 수 있는데,

IOCP의 경우 멀티스레드로 사용하는 경우가 대부분이기 때문에

동기화 문제가 발생할 가능성이 크다.

 

같은 핸들이 반환될 수 있기때문에, 동기화 문제가 발생할 가능성이 크다.

따라서, closesocket을 두번이상 호출하는 것은 위험성을 가지며,

closesocket을 호출하기 전에는 해당 소켓 핸들에 더이상 접근이 없음을 확실시 해야 한다.

 

2. 1Recv 1Post 가 가장 보편적이고 가장 편리하고 가장 깔끔하다.

(수신하고 - Post 를 반복한다.)

수신에 대한 완료 통지를 받으면 해당 스레드에서 다시 recv를 post하는 식으로 사용한다.

수신에 대한 완료통지는 무조건 딱 한번만 오기 때문에 종료 처리에 대한 로직 또한 매우 심플해진다.

 

3. post한 IO에 대한 카운트를 관리하여

연결종료시 post된 IO에 대한 완료 통지를 모두 받은 것을 확실시 한다. 

 

closesocket를 호출시

송신 및 수신은 더이상 사용할 수 없다.
송수신 함수를 호출하면 실패하며, 에러코드를 반환한다.

소켓 핸들은 OS로 반환되며 이 과정에서 post 된 IO가 있다면 모두 취소된다.

취소된 IO에 대해 IOCP 통지가 반드시 온다.

 

shutdown을 호출할 경우, shutdown 호출시 전달한 인자에 따라

송신 및 수신을 더이상 사용할 수 없게 만들 수 있다.

막힌 기능(송신 및 수신)을 수행하는 함수를 호출하면 당연히 실패하고, 에러코드를 반환한다.

허나 미리 post된 IO에 대해 확인은 불가능하다.

shutdown을 호출한다고 해서 pending 되어있던 IO 취소에 대한 통지는 오지 않는다.

 

CancelIoEx 의 경우,

post된 모든 IO는 취소되며, 이에 따른 IOCP 통지 또한 온다.

 

따라서, shutdown과 CancelIoEx를 차례대로 호출해서

송수신을 차단함과 동시에 이미 post된 모든 IO에 대해 취소하고,

설정해둔 IO 카운트 만큼 완료통지를 수집한다.

안전한 동기화가 확보된 이후에 closesocket을 호출할 수 있도록 한다.