Linux에서 실행되고 서버에 대한 TCP 연결을 생성하는 Java 및 cpp 클라이언트 애플리케이션이 있습니다. 이러한 애플리케이션은 TCP 연결을 설정한 후 이러한 TCP 연결의 Keepalive 매개변수를 수정합니다. 즉, Linux 기본 Keepalive 초인 7200초가 특정 TCP 연결에 대한 애플리케이션에서 300으로 수정됩니다.
$cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
$cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
$cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
소비자 보호 계획
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, 300, sizeof(int));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, 60, sizeof(int));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, 5, sizeof(int));
자바
sslSocket.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, 300);
sslSocket.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, 60);
sslSocket.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, 5);
내 질문은 Linux 터미널에서 설정된 TCP 연결(이러한 응용 프로그램에서 생성된 특정 연결에 대해)에 대한 연결 유지 간격/지연/프로브 카운트 값이 무엇인지 확인할 수 있는 방법이 있다는 것입니다.
애플리케이션에서 설정된 특정 TCP 연결을 식별한 후에는 해당 특정 연결에 대한 연결 유지 값을 인쇄하고 싶습니다(그리고 이러한 TCP 연결에 애플리케이션에서 설정한 연결 유지 값이 있는지 확인하고, OS 기본값이 아닌).
답변1
TCP 연결 유지는 두 피어 간에 독립적으로 존재합니다(서로의 설정을 협상하거나 알지 못함). 따라서 클라이언트에 연결 유지가 설정되어 있는지 (만) 확인할 수 있습니다
ss
(rt)netlink 소켓을 사용하는 최신 도구는 Linux에서는 더 이상 사용되지 않는 이 정보를 (적어도) 부분적으로 얻을 수 있습니다 . netstat
소켓 구성이 아닌 현재 상태를 검색할 수 있습니다.
예를 들어, 클라이언트는 호스트 192.0.2.4 포트 5555에 대한 연결을 설정했으며 연결 유지 유휴 시간이 120초로 설정되어 있습니다. socat
다음과 같이 재현 할 수 있습니다 .
socat -d -d tcp4:192.0.2.4:5555,keepalive=1,keepidle=120 -
-e / --extended
추가 옵션을 사용할 수 있습니다 ss
(커널 5.17.x 및IP 경로 25.18.0):
$ ss -tne dst == 192.0.2.4 and dport == 5555
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 192.0.2.3:40498 192.0.2.4:5555 timer:(keepalive,1min58sec,0) uid:1000 ino:4007748 sk:432 cgroup:/user.slice/user-1000.slice/session-2.scope <->
다음은 timer:(keepalive,1min58sec,0)
소켓의 현재 활성 상태 유지에 대한 정보입니다. 연결이 완료되기까지 약 2초 정도 소요되므로 1분 58초가 표시됩니다. 2mn 초기 구성은 여기에 제공되지 않습니다.
간단한 애플리케이션의 경우 GDB와 같은 디버거 도구를 사용하여 getsockopt(2)
시스템 호출을 주입하여 주어진 소켓에서 구성을 검색하고 표시할 수 있습니다( PID(여러 PID에서 공유할 수 있음) 및 FD 소켓을 검색하는 ss
옵션 도 필요함). -p
다음은 해당 정보가 특정 코어에 적용되지 않는 Q&A의 예입니다.탭 인터페이스와 해당 파일 설명자 간의 연결을 찾는 방법은 무엇입니까?
그러나 futex와 co의 스레드 간에 많은 동기화를 사용하는 Java와 같은 다중 스레드 애플리케이션의 경우 디버거를 사용하면 시간 제한 인터럽트로 인한 부작용이 없을지 확신할 수 없습니다.
답변2
내 생각엔 없는 것 같아예내가 아는 모든 쉘에서 이 작업을 수행하는 방법입니다. ss
이 정보 자체는 표시되지도 않습니다. 아마도 의미 있는 방식으로 다른 프로세스로 내보내지지 않은 프로세스 상태일 뿐입니다.
따라서 "도구형 디버거"가 아마도 이를 달성하는 유일한 방법일 것입니다.
ptrace
- 대상 프로세스에 연결하고 중지한 다음 [ 수행할 gdb
작업 ;call
실제로, 즉, 약간의 상태를 저장하고, 스택을 구축하고, 올바른 레지스터를 설정한 다음 명령 포인터를 로 설정하고, getsockopt
마지막 스택 프레임이 팝될 때까지 실행하고, 결과를 처리하고, 상태 및 원래 명령 포인터를 복원하고 계속 실행합니다. .
이것은 쉘에서 할 수 있는 일이 아닙니다!