이 소켓의 옵션을 소개하기 이전에, Time-wait 상태를 얘기하겠습니다.
우리가 서버를 키고 종료할 때 컨트롤-C 등으로 강제 종료하고 즉시 다시 키려고 시도하면 bind()함수에서 에러가 발생하는 모습을 이미 보셨을 수도 있습니다.
이 상황이 발생한 이유는 Time-wait 상태 때문인데, 데이터 송수신 중에 먼저 연결의 종료를 요청한 호스트는 Time-wait 상태를 거치게 됩니다. 만약 클라이언트와 통신 중에 위의 예시와 같이 강제종료 하는 등 서버가 먼저 종료되면, 서버가 Time-wait 상태를 거치게 되는 것입니다. 이 상태는 소켓이 소멸되지 않고 남아있게 됩니다.
(TCP에서 송수신이 종료되는 과정을 모르신다면 https://pupuduck.tistory.com/35를 참고해주시기 바랍니다.)
Time-wait 상태가 존재하는 이유는 만약 호스트A가 먼저 종료요청을 한 종료과정 마지막에 호스트A의 소켓이 ACK 메시지를 보내고 바로 소멸하게 되면, 그런데 여기서 호스트A의 ACK 메시지가 호스트 B에게 전달되지 않고 중간에 소멸된다면 호스트 B는 자신의 FIN 메시지가 호스트 A에게 전달되지 않았다고 보고 재 전송을 시도하게 됩니다. 하지만 호스트 A의 소켓은 소멸된 상태이므로 호스트 B는 마지막 ACK 메시지를 절대 받지 못하게 됩니다.
반면, 호스트 A의 소켓이 바로 소멸되지 않고 Time-wait 상태에 있다면 호스트 B로 마지막 ACK 메시지를 재전송하게 되고 호스트 B도 같이 정상종료할 수 있게 됩니다.
그런데, 시스템에 문제가 생겨 서버가 갑작스럽게 종료된 상황을 생각해보면, 빠르게 서버를 재가동시켜야 하는데 Time-wait 상태에 놓여있다면, 심지어 상대 호스트가 FIN메시지를 계속 보내 Time-wait가 계속해서 켜진다면 대참사가 일어날 것입니다. 그래서 존재하는 소켓의 옵션이 SO_REUSEADDR입니다.
SO_REUSEADDR 옵션은 값이 TRUE(1)일 때 이미 소켓에 할당되어 있는 PORT번호를 새로 만든 소켓에 할당할 수 있게 합니다. 예시는 다음과 같습니다.
optlen = sizeof(option);
option=TRUE;
setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&option, optlen);
이 옵션 설정을 거치면 Time-wait 상태에서도 서버를 다시 켤 수 있게 됩니다.
'현생 > TCP 소켓 프로그래밍' 카테고리의 다른 글
10-1. 다중접속서버의 필요성과 멀티프로세스 [TCP/IP][C][LINUX] (0) | 2022.01.26 |
---|---|
9-5 Nagle 알고리즘과 중단하는 소켓의 옵션 [TCP/IP][C][LINUX] (0) | 2022.01.25 |
9-3 입출력 버퍼를 다루는 소켓의 옵션 [TCP/IP][C][LINUX] (0) | 2022.01.24 |
9-2. 소켓의 타입을 확인하는 소켓의 옵션 [TCP/IP][C][LINUX] (0) | 2022.01.24 |
9-1. 소켓의 옵션과 설정 함수 get/setsockopt [TCP/IP][C][LINUX] (0) | 2022.01.24 |