-
생각보다 쉽지만은 않은 SO_LINGER개발/서버 2019. 10. 22. 16:35
소켓을 설정할 때 나오는 옵션 중 SO_LINGER와 SO_DONTLINGER가 있다. 시중에서 판매되는 책에는 설명이 비교적 간단한데, 사용법은 보통 다음과 같다.
12345LINGER linger = { 0, 0 };linger.l_onoff = 1; // SO_LINGERlinger.l_linger = 0; // TIME-OUTsetsockopt(socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof linger);closesocket(socket);설명에 따르면 closesocket 함수의 디폴트 동작은 SO_DONTLINGER이다. 소켓을 통한 추가적인 데이터 송수신이 안 되지만 커널의 송신 버퍼에 있던 데이터는 상대에게 전부 보낸다. 상대에게 FIN_ACK을 받으면 정상종료된다. closesocket()이 즉시 반환되기 때문에 커널에서 수행하는 작업이 언제 끝날지 알 수 없다.
이 동작을 변경하고 싶으면 위의 예처럼 LINGER 구조체 변수를 하나 만들고 l_onoff에 0이 아닌 값을 대입하면 SO_LINGER으로 동작하는데 LINGER 구조체의 l_linger에 넣는 값에 따라 동작 시간이 달라진다고. 이를 이용해 l_onoff에 nonzero를 넣고 l_linger에 0을 대입하면 송신 버퍼에 있는 데이터는 즉시 폐기된다. 일종의 강제 종료라고 보면 된다.
궁금했던 부분은 linger라는 뜻이 '남다'라는 의미를 가지고 있는데 이 단어의 의미와 동작이 잘 연결되지 않았던 점이다. linger라는 단어가 매칭되는 대상은 소켓인 듯하다. l_onoff가 nonzero이면서 l_linger도 nonzero라면 소켓을 설정한 시간만큼 열어둔 상태에서 커널이 클라이언트에서 보내는 FIN 패킷을 기다린다. 즉 closesocket 함수를 호출한 쪽은 FIN_ACK 패킷을 받을 때까지 커널에서 기다린다는 의미다. 하지만 남아 있는 데이터가 송신되고 상대로부터 ACK를 받기 전에 대기 시간이 만료된다면 EWOULDBLOCK을 리턴하면서 송신 버퍼에 있던 데이터는 폐기된다.
'개발 > 서버' 카테고리의 다른 글
WSAEventSelect 모델 (0) 2021.11.14 [Hyper-V] 게스트에 고정 IP 주기 (4) 2019.09.02