unix c로된 tcp/ip통신프로세스가 정상종료후
netstat -na|grep 7000 로 조회하면
tcp 0 0 160.17.8.146.7000 160.17.8.198.32836 FIN_WAIT_2
와같이 FIN_WAIT_2 상태가 계속 오래 지속되어
바로 기동하면
Address already in use
라고 나옵니다.
정상종료후 바로기동이 가능하게 하려면 어떻게 하면되는지요?
30분이 넘도록,
Address already in use
가 발생하여 서버가 기동을 못하고 있습니다.
그래서,
if ( setsockopt( m_fdListenSock , SOL_SOCKET , SO_REUSEADDR , &optval , sizeof optval ) < 0 )
을 주었더니, 기동은 되는데요. 서버가 정상종료하면 클라이언트가 먹통이 된다네요.이것을 어떻게 해결할지?
흠
FIN_WAIT_2는
1. 내 프로그램이 close()를 호출
(이때 상대에게 FIN 을 보냄)
2. 상대가 FIN에 대한 ACK를 보냄
3. 나는 상대가 FIN을 보내기를 기다리고 잇음
(근데 상대는 아직 FIN을 안보내고 있음, 아직 데이타를 보내고 있을지도 모름)
이 상태에 있는 소켓의 상태가 FIN_WAIT2 입니다.
하나의 TCP 소켓에 대해 두개의 경로가 있는데
하나는 보내기 위한 경로이고 하나는 받기 위한 경로입니다.
close()호출시 FIN이 전달되는데
이 FIN의 의미는 내가 보내는 경로를 닫기 위한 것이며
ack를 받았으면 보내는 경로가 닫힙니다.
이때 상대의 받는 경로는 닫히겠죠 (나의 보내는 경로=상대의 받는경로)
FIN_WAIT2 상태라면 내가 FIN 보내고 ack를 수신했는데
아직 상대는 자신의 보내는 흐름을 닫기 위해 FIN을 보내지는 않았고
그래서 소켓의 받기 위한 경로가 아직 닫히지 않은 상태입니다.
아마도 상대가 아직 보낼데이타가 더 있기 때문에
FIN을 보내고 있지 않을까 하는 생각이 듭니다.
이러한 처리를 확실히 하기 위해서는
close()보다 shutdown()을 사용해서 아래의 절차를
통해서 연결을 끝맺는 것이 올바를것 같습니다.
1. 보내는 경로 shutdown()
2. while( read(sock, buf,size) > 0) { ... }
3. 받는 경로 shutdown()
read()가 0을 수신하면 상대로 부터 FIN을 받은 것이 됩니다.
그러면 이제 나의 소켓은 2*MSL의 시간동아
TIME_WAIT상태에 빠져들게 됩니다.
TIME_WAIT상태든 FIN_WAIT 상태든...이 상태에서는
같은 포트번호에 소켓을 바인드조차 할수 없습니다.
(리슨하기 위해서는 바인드먼저해야하잔아요)
단. SO_REUSEADDR 소켓옵션을 사용하면 바인드가 성공하도록 할수 있습니다.
소켓에 SO_REUSEADDR 소켓옵션을 true 상태로 만들어주어야 합니다.
(기본값은 false)
int on = 1; // true
setsockopt(sock SOL_SOCKET, SO_REUSEADDR, &on);
30분이 넘도록,Address already in use 가 발생
30분이 넘도록,
Address already in use
가 발생하여 서버가 기동을 못하고 있습니다.
그래서,
if ( setsockopt( m_fdListenSock , SOL_SOCKET , SO_REUSEADDR , &optval , sizeof optval ) < 0 )
을 주었더니, 기동은 되는데요. 서버가 정상종료하면 클라이언트가 먹통이 된다네요.이것을 어떻게 해결할지?
FIN_WAIT2
흠
FIN_WAIT_2는
1. 내 프로그램이 close()를 호출
(이때 상대에게 FIN 을 보냄)
2. 상대가 FIN에 대한 ACK를 보냄
3. 나는 상대가 FIN을 보내기를 기다리고 잇음
(근데 상대는 아직 FIN을 안보내고 있음, 아직 데이타를 보내고 있을지도 모름)
이 상태에 있는 소켓의 상태가 FIN_WAIT2 입니다.
하나의 TCP 소켓에 대해 두개의 경로가 있는데
하나는 보내기 위한 경로이고 하나는 받기 위한 경로입니다.
close()호출시 FIN이 전달되는데
이 FIN의 의미는 내가 보내는 경로를 닫기 위한 것이며
ack를 받았으면 보내는 경로가 닫힙니다.
이때 상대의 받는 경로는 닫히겠죠 (나의 보내는 경로=상대의 받는경로)
FIN_WAIT2 상태라면 내가 FIN 보내고 ack를 수신했는데
아직 상대는 자신의 보내는 흐름을 닫기 위해 FIN을 보내지는 않았고
그래서 소켓의 받기 위한 경로가 아직 닫히지 않은 상태입니다.
아마도 상대가 아직 보낼데이타가 더 있기 때문에
FIN을 보내고 있지 않을까 하는 생각이 듭니다.
이러한 처리를 확실히 하기 위해서는
close()보다 shutdown()을 사용해서 아래의 절차를
통해서 연결을 끝맺는 것이 올바를것 같습니다.
1. 보내는 경로 shutdown()
2. while( read(sock, buf,size) > 0) { ... }
3. 받는 경로 shutdown()
read()가 0을 수신하면 상대로 부터 FIN을 받은 것이 됩니다.
그러면 이제 나의 소켓은 2*MSL의 시간동아
TIME_WAIT상태에 빠져들게 됩니다.
TIME_WAIT상태든 FIN_WAIT 상태든...이 상태에서는
같은 포트번호에 소켓을 바인드조차 할수 없습니다.
(리슨하기 위해서는 바인드먼저해야하잔아요)
단. SO_REUSEADDR 소켓옵션을 사용하면 바인드가 성공하도록 할수 있습니다.
소켓에 SO_REUSEADDR 소켓옵션을 true 상태로 만들어주어야 합니다.
(기본값은 false)
댓글 달기