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


113

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

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


1
당신으로 인해 여기 경우 "너무 많은 TIME_WAIT서버에서" 바로 건너 뛸 를 대답 대신 질문을 피하기 처음 세 개의 답변.
Pacerier

답변:


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


8
큰 대답이지만 그의 질문에 대한 정답은 아닙니다. 네트워킹을 다시 시작하면 작동하지만 다시 부팅되므로 제대로 할 수 없습니다.
Chris Huang-Leaver

3
@Chris Huang-Leaver, 문제는 "소켓이 TIME_WAIT 상태에서 즉시 빠져 나가도록 실행할 수있는 프로그램이 있습니까?" 재부팅이 프로그램 실행을 고려할 수 있다면 올바른 대답이 될 것입니다. 왜 이것이 옳지 않다고 생각합니까?
유진 요코타

8
WMR은 가장 유용한 답변을 가지고 있습니다 (이런 종류의 문제에 부딪 칠 때 내가하는 일입니다). 너무 과감한 네트워크입니다 다시 시작하면 솔루션으로, 단순히 자신의 질문에 timeout.The 정답은 '아니오',하지만 그래서 당신은이 편지 답변 :-)를 입력 못하게되어 대기보다 더 오래 걸릴 수 있습니다
크리스 Huang- Leaver

6
오, 좋아, 다음에 SIGTERM에서 프로세스가 멈 추면 컴퓨터를 고치는 대신 부 s 버리겠다.
Longpoke

이것의 일반화는 "네트워크 서비스 재시작"입니다. 특정 위치 /etc/init.d/networking는 플랫폼에 따라 다르므로 (Debian?) 정확한 명령 줄은 다른 시스템에 따라 다를 수 있습니다 (때로는 다소 급진적 임). 나는 다른 의견 제시 자들과 관련이 있으며 이는 관련없는 네트워크 서비스에 대해 심각한 과잉과 명백히 파괴적 인 것 같습니다.
트리플 리

51

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

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


그러나 나는 이미 바운드 오류를 얻지 못했습니다. 프로그램을 다시 실행하면 post (123456)에서 수신 대기합니다. 또한 시스템이 해당 포트에 대해 TIME_WAIT를 표시하지만 여전히 연결할 수 있음을 알 수 있습니다. 왜?
Jayapal Chandran

2
SO_REUSEADDR을 사용해도 "주소가 이미 사용 중"오류가 계속 발생할 수 있습니다. 자세한 내용은 hea-www.harvard.edu/~fine/Tech/addrinuse.html을 참조하십시오 .
Jingguo Yao

@WMR SO_REUSEADDR은 소켓을 "닫지"않습니다. 이미 열려있는 것을 재사용 할 수 있습니다. 따라서 문제는 여전히 "강제로 소켓을 닫는 방법은 TIME_WAIT무엇입니까?"입니다.
Pacerier

이것은 정답이지만 질문은 완전히 정확하지 않습니다. 적어도 내 문제를 잘 해결했습니다 (전체 네트워크를 다시 시작하여 다른 모든 연결을 끊는 것처럼).
V-Mark

SO_REUSEADDRbind()진행 하겠습니다 ; 그러나 그 소켓을 듣고 싶다면 모두 똑같이 listen()반환 EADDRINUSE합니다. 즉,이 답변은 임시 포트를 사용하는 클라이언트 소프트웨어에 도움이 될 수 있지만 서버 소프트웨어의 문제는 해결하지 못합니다.

33

내가 아는 한 더 나은 신호 처리기를 프로그램에 쓰는 것 외에는 소켓을 강제로 닫을 수있는 방법이 없지만 시간 초과가 걸리는 시간을 제어하는 ​​/ 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 씩 증가하도록 프로그램을 작성해야합니다. 따라서 소스 코드를 제어 할 수있는 경우이 동작을 변경하여 몇 초 동안 기다렸다가 동일한 포트에서 다시 시도하지 않고 증가시킬 수 있습니다.


두 번째 두 가지 예는 s / rw / tw /이어야한다고 생각하지만 충분한 담당자가 없습니다.

1
커널 문서에서 가져 왔습니다 :주의. tcp_tw_recycle 및 tcp_tw_reuse 모두 ​​문제를 일으킬 수 있습니다. 매개 변수가 사용 가능한 노드에서 사용하거나 사용하는 노드 사이의 네트워크 토폴로지를 이해하지 않고 사용하지 않아야합니다. 방화벽, NAT 또는로드 밸런서와 같은 TCP 연결 상태를 인식하는 노드를 통과하는 연결은 설정으로 인해 프레임 삭제를 시작할 수 있습니다. 연결 수가 충분하면 문제가 나타납니다.

1향후 연결 을 위해 작동 하도록 설정 했지만 이미 열려있는 현재 연결은 어떻습니까?
Pacerier

18

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

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


3

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


2
또한 아직 전송중인 아웃 바운드 데이터가 손실되고 다른 쪽 끝에 오류가 발생할 수 있습니다. 권장하지 않습니다.
207421

@EJP 조기 실패는 거의 항상 올바른 전화입니다. 네트워킹은 신뢰할 수 없으며 싸움으로 인해 속도가 느려집니다. 충돌 한 앱은 데이터가 안전하게 만들어 졌다고 가정 할 수 없습니다.
Tobu

1
실제로 다른 엔드 포인트가 TCP를 통한 자체 응용 프로그램 계층의 안정적인 전송을 구현하는 버그가있는 임베디드 산업용 버스 게이트웨이 인 경우에는 언젠가이 방법을 권장합니다. 해당 게이트웨이의 연결 제한 그곳에. 슬프게도 이와 같은 핵에 의존해야하는 매우 구체적이고 실제적인 예를 들었습니다.
andyn

@Tobu Networking은 신뢰할 수 없지만 TCP는 노력하고 있으며, 더 나쁘게 만드는 것이 더 나은 것을 만드는 것은 아니며 TCP가 그 일을하게하는 것은 '싸움'을 구성하지 않습니다.
user207421

2

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

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


0

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.