Linux 플랫폼에서 소켓을 사용할 때 파일 디스크립터 누출이 있습니까?
-
07-07-2019 - |
문제
예를 들어 전화하여 소켓을 열고 닫는 경우
Socket s = new Socket( ... );
s.setReuseAddress(true);
in = s.getInputStream();
...
in.close();
s.close();
Linux는이 소켓이 여전히 열려 있거나 최소한 연결의 파일 디스크립터가 사전에 있다고 명시하고 있습니다. LSOF 가이 프로세스의 열린 파일을 쿼리 할 때 닫힌 연결을위한 항목이 있습니다.
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
java 9268 user 5u sock 0,4 93417 can't identify protocol
이 항목은 프로그램이 닫힐 때까지 유지됩니다. 마침내 소켓을 닫을 수있는 다른 방법이 있습니까? Java 응용 프로그램이 많은 파일 설명자로 차단할 수 있을까 걱정됩니다. 이게 가능해? 아니면 Java 가이 소켓을 재사용하기 위해이 소켓을 재사용해야합니까?
해결책
해당 소켓이 모두 Time_wait 상태에 있으면 적어도 잠시 동안 정상입니다. Netstat로 확인하십시오. 새 소켓을 위해 포트를 재사용하기 전에 소켓에서 깎아내는 데이터가 성공적으로 버려 지도록 소켓이 몇 분 동안 매달려있는 것이 일반적입니다.
다른 팁
당신은 또한 확인하고 싶을 수도 있습니다 /proc/<pid>/fd
, 디렉토리에는 현재 열린 모든 파일 설명자가 포함됩니다. 소켓을 닫은 후 파일이 사라지면 문제가 발생하지 않습니다 (적어도 파일 설명자와 관련이 없습니다 :).
나는 그것이 당신의 프로그램의 문제가 아니라고 생각합니다.
Sun_java에서는 소켓 관련 기본 LIB가로드되면 Magic_Sock FD가 생성됩니다.
Magic_Sock에 쓰기로 인해 Connect REST 예외가 발생하고 Magic_Sock을 읽으면 EOF가 나타납니다.
Magic_Sock의 피어는 완전히 닫혀 있었고 Magic_Sock 자체는 Half_Closed이며 상태는 "프로토콜을 식별 할 수 없습니다".
어쩌면 그것은 다른 프로토콜 ( "프로토콜을 식별 할 수 없음"eh?)의 소켓 일 수 있습니다.
이 소켓이 실제로 지속되는지 확인하기 위해 반복적으로 소켓을 만들고 닫으려고 했습니까? 이것은 일회성 일 것 같습니다.
Java는 아마도 많은 것을 위해 내부적으로 소켓을 사용합니다 - 그들은 Unix, NetLink (Linux) 또는 다른 유형의 소켓 일 수 있습니다.
특정 앱 또는 PID의 열린 소켓을 모니터링하는 작은 bash 스크립트를 만들고 Java 앱을 테스트하는 동안 실행하도록하십시오.
어쨌든 소켓은 Linux/Unix World에서 소켓이 매우 사용되며 이러한 종류의 문제가 매우 빠르게 거품이 될 것입니다.