TCP/IP 소켓 옵션
feat. SO_REUSEADDR
📌 Server를 생성하고 Client 가 접속한 후 Client가 접속된 상태에서 Server를 종료시키고자 한다. Server socket과 accept로 생성된 socket을 close() 함수로 종료한 후 Task를 다시실행하였더니 bind error 가 발생하였다. 즉 Socket 이 제대로 닫히지 않은 것 이다.
최초에는 서로 통신 상태이기 때문에 양쪽이 ESTABLISHED 상태이다.
최종 ACK를 받은 서버는 자신의 포트도 CLOSED로 닫게 된다. 현재 포트의 상태는 netstat
명령어를 통해 확인할 수 있다. 위와 같이 종료과정을 살펴보면 close()
호출후에도 대기 시간이 발생한다. 이와 같은 소켓 재사용 문제를 해결하기 위해 소켓옵션을 사용한다.
SO_REUSEADDR
옵션을 설정하면 커널이 소켓을 사용하는 중에도 계속해서 사용할 수 있다. 이 옵션은 서버프로그램이 종료된 후에도 커널이 소켓의 포트를 아직 점유 중인 경우에 서버 프로그램을 다시 구동해야 할 때 매우 유용하다.
예를 들어, 연결 종료 단계에서 설명한 바와 같이 연결 종료를 먼저 시작한 쪽은 상대방으로부터 FIN 패킷을 받고, FIN_ACK 패킷을 전송한 후 일정 시간 동안 소켓을 종료하지 않고 커널이 해당 소켓을 점유한다.
즉, 먼저 종료를 시작하는 시스템은 응용 프로그램이 종료되더라도 소켓은 커널에서 일정 시간 동안 점유 중인 상태로 있게 되는 것이다. 이런 경우에 응용 프로그램을 재실행하면 bind
함수를 호출할 때 아직 점유 중인 포트를 연결하려는 시도 때문에 오류가 발생한다. 일정 시간이 지나야 연결이 가능하다.
게임 서버처럼 사용자가 많은 서버에서 버전 업그레이드 때문에 일정 시간 동안 서버를 중단했다가 다시 구동해야 하는 경우에도 이런 문제가 발생한다. 일정 시간 서비스를 할 수 없는 것이다. 이때 SO_REUSEADDR
옵션을 설정하면 커널이 소켓의 포트를 점유 중인 상태에서도 서버 프로그램을 다시 구동할 수 있다.
이 밖에도 두 개 이상의 IP 주소를 갖는 호스트에서 IP 주소별로 서버를 운용할 경우에도 이 옵션을 사용하면 사용 중인 포트에 대해서도 소켓을 성공적으로 주소에 연결(bind)할 수 있다. 멀티캐스팅 응용 프로그램이 동일한 포트를 사용할 때도 이 옵션을 활용한다.
함수 원형 (VxWorks)
🔔 예)
int optval = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
bind(s, &sin, sizeof(sin));
[소켓 프로그래밍] SO_KEEPALIVE 옵션 사용법/SO_LINGER 옵션 사용법 (0) | 2024.03.05 |
---|