동일한 Linux 시스템에서 실행되는 서버 프로세스와 클라이언트 프로세스가 있습니다.
가끔 kill -9
클라이언트일 때 메시지가 전송되는 것을 볼 수 tcpdump
있습니다 FIN, ACK
. 물론 죽은 의뢰인은 잔혹하게 죽었기 때문에 이런 일을 할 수는 없을 것이다 SIGKILL
. 그래서 Linux OS가 연결 종료를 처리하는 것 같아요.
때로는 연결 종료 처리가 표시되지 않고 연결이 "설정됨" 상태로 유지되는 경우도 있습니다( netstat
).
연결이 계속 닫히는 것을 볼 수 있습니다 Linux ubuntu 4.4.0-53-generic
.
때때로Linux 3.13.11
(Ubuntu가 아닌 순수 커널)에서 연결이 닫히는 것을 볼 수 있습니다.
내 질문은 다음과 같습니다
- Linux는 연결 종료를 처리합니까?
1.1 어디SIGKILL
?
1.2.애플리케이션이 올바르게 종료되었지만 호출되지 않는 경우close()
? - 커널 버전 간에 이 기능이 변경됩니까
3.13.11
?4.4.0
우분투와 관련된 것이 있나요? - 두 프로세스가 동일한 Linux 시스템에 있지 않으면 어떻게 되나요? 동일하게 작동합니까?
- 연결이 때때로 "설정된" 상태로 유지되는 이유는 무엇입니까?
keepalive
TCP 소켓 옵션 에 대해 알고 있습니다 . Linux가 실제로 연결 종료를 처리하는 경우. 왜 존재합니까?FIN, ACK
패킷이 손실된 경우에만 ?
답변1
광범위한 질문입니다. 어쩌면 누군가가 특정 커널 버전 간의 커널 TCP 스택에 대한 귀하의 질문에 무게를 둘 수 있습니다.
몇 가지 일반적인 답변:
클라이언트에서
신호가 발생 하면
SIGKILL
커널은 프로그램 실행을 종료하고 프로세스의 열린 파일 설명자를 닫습니다. 커널은 TCP 소켓을 플러시하고 TCP 종료 프로세스를 거쳐야 한다는 점에서 일반 파일과 약간 다르게 TCP 소켓을 처리합니다.클라이언트의 즉각적인 "FIN, ACK"와 더 긴 소켓 닫기 간의 차이는 클라이언트 애플리케이션이 종료될 때 클라이언트 TCP 연결 상태에 따라 달라질 수 있습니다. 그러나 일반적으로 커널은 애플리케이션이 연 소켓을 닫습니다.
서버 측에서
서버는 클라이언트 연결이 언제 끊어지는지 항상 알 수는 없습니다. 클라이언트가 정지되었는지 확인하는 가장 신뢰할 수 있는 방법은 EOF를 반환하는 소켓에서 읽기를 시도하는 것입니다.
TCP는 연결 지연과 간헐적인 오류를 견딜 수 있도록 설계되었습니다. 이는 또한
FIN, ACK
4방향 연결 해제 핸드셰이크가 발생하지 않고 연결 해제를 안정적으로 감지하는 데 몇 가지 문제가 있음을 의미합니다 .
일반화하다
kill -9
클라이언트 측에서 서버가 CLOSE_WAIT
TCP 상태에 들어가고 TCP 시간 초과를 기다리는 것을 볼 수 있습니다 . 시간이 좀 걸릴 수 있습니다. 클라이언트가 사라지더라도 커널이 TCP 연결 해제 핸드셰이크를 처리하지 않으면 서버는 시간 초과되어야 합니다.
ESTABLISHED
내 기억으로는 이 작업에 몇 초가 더 걸릴 수 있으며 동일한 호스트에서 클라이언트와 서버를 실행하기 때문에 이 메시지가 계속 표시되는 이유일 수 있습니다 .