[server] TIME_WAIT에서 소켓을 강제로 닫는 방법은 무엇입니까?

때로는 충돌하는 Linux에서 특정 프로그램을 실행합니다. 그 후에 빨리 열면 처음처럼 소켓이 49200 대신 49201에서 수신 대기합니다. netstat는 49200이 TIME_WAIT 상태임을 나타냅니다.

해당 소켓이 TIME_WAIT 상태를 벗어나도록 즉시 실행할 수있는 프로그램이 있습니까?



답변

/etc/init.d/networking restart

자세히 설명하겠습니다. TCP (Transmission Control Protocol)는 두 개의 엔드 포인트 (프로그램) 사이에서 양방향의 순서가 있고 신뢰할 수있는 데이터 전송 프로토콜이되도록 설계되었습니다. 이와 관련하여 신뢰할 수있는 용어는 패킷이 중간에 손실 될 경우 패킷을 재전송한다는 것을 의미합니다. TCP는 피어로부터 수신 한 단일 또는 일정 범위의 패킷에 대해 ACK (Acknowledgement) 패킷을 다시 전송하여 안정성을 보장합니다.

이것은 종료 요청 / 응답과 같은 제어 신호에 대해서도 동일합니다. RFC 793 은 TIME-WAIT 상태를 다음과 같이 정의합니다.

TIME-WAIT-원격 TCP가 연결 종료 요청에 대한 승인을 수신 할 수 있도록 충분한 시간 동안 대기 중임을 나타냅니다.

다음 TCP 상태 다이어그램을 참조하십시오.
대체 텍스트

TCP는 양방향 통신 프로토콜이므로 연결이 설정 될 때 클라이언트와 서버간에 차이가 없습니다. 또한 둘 중 하나가 통화를 종료 할 수 있으며, 두 피어는 설정된 TCP 연결을 완전히 종료하기 위해 종료에 동의해야합니다.

첫 번째를 호출하여 종료를 활성 클로저로 호출하고 다른 피어를 패시브 클로저로 호출합시다. 액티브 클로저가 FIN을 보내면 상태는 FIN-WAIT-1이됩니다. 그런 다음 전송 된 FIN에 대한 ACK를 수신하고 상태는 FIN-WAIT-2로 이동합니다. 패시브 클로저에서도 FIN을 수신하면 액티브 클로저는 ACK를 FIN으로 보내고 상태는 TIME-WAIT로 이동합니다. 패시브 클로저가 제 2 FIN에 대한 ACK를 수신하지 못한 경우, FIN 패킷을 재전송 할 것이다.

RFC 793 은 TIME-OUT을 최대 세그먼트 수명의 2 배 또는 2MSL로 설정합니다. 패킷이 인터넷을 돌아 다닐 수있는 최대 시간 인 MSL은 2 분으로 설정되고 2MSL은 4 분입니다. ACK에 대한 ACK가 없기 때문에 액티브 클로저는 TCP / IP 프로토콜을 올바르게 준수하면 수동 송신자가 ACK를 FIN에 대한 ACK를받지 못한 경우를 대비하여 4 분 동안 대기 할 수 있습니다. .

실제로, 누락 된 패킷은 드물고 LAN 또는 단일 시스템 내에서 모두 발생하는 경우에는 매우 드 rare니다.

TIME_WAIT에서 강제로 소켓을 닫는 방법?이라는 질문에 답하기 위해 여전히 원래의 대답을 고수합니다.

/etc/init.d/networking restart

실제로 말하면 WMR에서 언급 한대로 SO_REUSEADDR 옵션을 사용하여 TIME-WAIT 상태를 무시하도록 프로그래밍합니다. SO_REUSEADDR은 정확히 무엇을합니까?

이 소켓 옵션은 커널에이 포트가 사용 중이더라도 (
TIME_WAIT 상태) 계속 진행하여 다시 사용하도록 알려줍니다 . 사용 중이지만 다른 상태 인 경우에도 이미 사용중인 주소 오류가 발생합니다. 서버가 종료 된 다음 포트에서 소켓이 여전히 활성 상태 인 동안 즉시 다시 시작하면 유용합니다. 예기치 않은 데이터가 들어 오면 서버를 혼란스럽게 할 수 있지만 이것이 가능하지만 가능하지는 않습니다.


답변

실행중인 특정 프로그램의 소스 코드가 있는지 모르겠지만 setsockopt(2)소켓이 TIME_WAIT 상태에 있더라도 동일한 로컬 주소에 바인딩 할 수있는 SO_REUSEADDR을 설정할 수 있습니다 ( 소켓이 적극적으로 듣고 있습니다 (참조 socket(7)).

TIME_WAIT 상태에 대한 자세한 내용은 Unix 소켓 FAQ를 참조하십시오 .


답변

내가 아는 한 더 나은 신호 처리기를 프로그램에 쓰는 것 외에는 소켓을 강제로 닫을 수있는 방법이 없지만 시간 초과가 걸리는 시간을 제어하는 ​​/ proc 파일이 있습니다. 파일은

/proc/sys/net/ipv4/tcp_tw_recycle

다음을 수행하여 시간 초과를 1 초로 설정할 수 있습니다.

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle

그러나이 페이지 에는이 변수를 설정할 때 발생할 수있는 안정성 문제에 대한 경고가 포함되어 있습니다.

관련 파일도 있습니다

/proc/sys/net/ipv4/tcp_tw_reuse

TIME_WAIT 소켓을 재사용 할 수 있는지 여부를 제어합니다 (아마 시간 초과없이).

또한 커널 설명서는 ‘기술 전문가의 조언 / 요청’없이 이러한 값을 변경하지 말 것을 경고합니다. 내가 아니야

포트 49200에 대한 바인딩을 시도한 다음 포트가 이미 사용중인 경우 1 씩 증가하도록 프로그램을 작성해야합니다. 따라서 소스 코드를 제어 할 수있는 경우이 동작을 변경하여 몇 초 동안 기다렸다가 동일한 포트에서 다시 시도하지 않고 증가시킬 수 있습니다.


답변

실제로 연결을 끊는 방법은 killcx 입니다. 그들은 그것이 연결 상태 (내가 확인하지 않은)에서 작동한다고 주장합니다. 통신이 발생하는 인터페이스를 알아야하며 기본적으로 eth0으로 가정합니다.

업데이트 : 또 다른 솔루션은 일부 Linux 배포판의 저장소에 제공되는 커터 입니다.


답변

다른 옵션은 시간 종료 0으로 SO_LINGER 옵션을 사용하는 것입니다.이 방법으로 소켓을 닫으면 강제로 닫히고 FIN / ACK 닫기 동작으로 들어 가지 않고 RST를 보냅니다. TIME_WAIT 상태를 피할 수 있으며 일부 용도에 더 적합 할 수 있습니다.


답변

다른 해결책은 포트 49200에서 수신 대기하는 안정적인 프록시 또는 포트 포워딩 소프트웨어를 갖고 다른 포트를 사용하여 신뢰성이 낮은 프로그램의 여러 인스턴스 중 하나에 연결을 전달하는 것입니다. HAPROXY가 떠 오릅니다.

또한 연결하는 포트가 상당히 높습니다. 0-1024 범위 바로 위에서 사용하지 않는 것을 사용해 볼 수 있습니다. 시스템은 짧은 포트 번호를 임시 포트로 사용할 가능성이 적습니다.


답변

TIME_WAIT는 소켓 프로그래밍 클라이언트 서버 아키텍처에서 가장 일반적인 문제입니다. 주기적으로 시도하는 것이 가장 좋은 해결책입니다. 실시간 응용 프로그램의 경우 서버가 즉시 시작되어야합니다. SO_REUSEADDR 옵션이 있습니다.