HTTP 연결 유지에 대해 들어 봤지만 지금은 원격 서버와 소켓 연결을 열고 싶습니다.
이제이 소켓 연결이 영원히 열려 있거나 HTTP 연결 유지와 유사한 시간 제한이 있습니까?
HTTP 연결 유지에 대해 들어 봤지만 지금은 원격 서버와 소켓 연결을 열고 싶습니다.
이제이 소켓 연결이 영원히 열려 있거나 HTTP 연결 유지와 유사한 시간 제한이 있습니까?
답변:
TCP 소켓은 닫힐 때까지 열려 있습니다.
즉, 실제로 데이터를 전송하지 않고 끊어진 연결 (라우터에서 끊어진 것과 같은 끊어짐 등)을 실제로 데이터를 전송하지 않고 감지하는 것은 매우 어렵 기 때문에 대부분의 응용 프로그램은 확인하기 위해 자주 일종의 핑 / 퐁 반응을 수행합니다. 연결은 실제로 살아 있습니다.
이제이 소켓 연결이 영원히 열려 있거나 HTTP 연결 유지와 유사한 시간 제한이 있습니까?
짧은 대답은 ' 아니오 '입니다. 영원히 열려 있지 않으며 몇 시간 후에 시간이 초과 될 것입니다. 따라서 예 가 있다 타임 아웃 그것은을 통해 적용됩니다 TCP 연결 유지 .
컴퓨터에서 Keep-Alive 제한 시간을 구성하려면 아래의 "TCP 제한 시간 변경"섹션을 참조하십시오. 그렇지 않으면 나머지 답변을 읽고 TCP Keep-Alive 작동 방식을 알아보십시오.
TCP 연결은 연결의 각 끝에 하나씩 두 개의 소켓으로 구성됩니다. 한 쪽이 연결을 종료하려고 할 때 RST
다른 쪽이 확인하고 소켓을 닫는 패킷을 보냅니다 .
그러나 그렇게 될 때까지 양측은 소켓을 무기한으로 열어 둡니다. 이렇게하면을 통해 다른 쪽 끝에 알리지 않고 의도적으로 또는 일부 오류로 인해 한쪽이 소켓을 닫을 가능성이 열립니다 RST
. 이 시나리오를 감지하고 오래된 연결을 닫으려면 TCP Keep Alive 프로세스가 사용됩니다.
Keep-Alives 작동 방식을 결정하는 세 가지 구성 가능한 속성이 있습니다. Linux에서는 1입니다 .
tcp_keepalive_time
tcp_keepalive_probes
tcp_keepalive_intvl
프로세스는 다음과 같이 작동합니다.
tcp_keepalive_time
몇 초 동안 침묵 하면 하나의 빈 ACK
패킷을 보냅니다 . 1ACK
가 자체적으로 응답 했습니까 ?
tcp_keepalive_intvl
몇 초 동안 기다린 다음 다른 메시지를 보냅니다.ACK
ACK
전송 된 프로브 수가 같을 때까지 반복하십시오 tcp_keepalive_probes
.RST
연결을 종료하십시오.이 프로세스는 대부분의 운영 체제에서 기본적으로 활성화되어 있으므로 다른 쪽 끝이 2 시간 11 분 (7200 초 + 75 * 9 초) 동안 응답하지 않으면 작동하지 않는 TCP 연결이 정기적으로 정리됩니다.
연결이 기본적으로 2 시간 동안 유휴 상태가 될 때까지 프로세스가 시작되지 않기 때문에 부실 TCP 연결이 정리되기 전에 매우 오랫동안 지속될 수 있습니다. 이는 데이터베이스 연결과 같은 값 비싼 연결에 특히 해로울 수 있습니다.
RFC 1122 4.2.3.6 에 따르면 TCP Keep-Alive 패킷에 대한 응답 및 / 또는 릴레이 는 선택 사항입니다 .
구현자는 TCP 구현에 "keep-alive"를 포함 할 수 있지만이 관행은 보편적으로 받아 들여지지는 않습니다. 연결 유지가 포함 된 경우 응용 프로그램은 각 TCP 연결에 대해 해당 연결을 켜거나 끌 수 있어야하며 기본적으로 꺼져 있어야합니다.
...
데이터가없는 ACK 세그먼트는 TCP에 의해 안정적으로 전송되지 않는다는 점을 기억하는 것이 매우 중요합니다.
Keep-Alive 패킷은 데이터를 포함하지 않으며 엄격하게 필요하지 않으며 과도하게 사용되는 경우 인터 웹의 튜브가 막힐 위험이 있기 때문입니다.
그러나 실제로 는 대역폭이 저렴 해짐에 따라 시간이 지남에 따라 이러한 우려가 줄어 들었습니다. 따라서 Keep-Alive 패킷은 일반적으로 삭제되지 않습니다. 예를 들어 Amazon EC2 설명서 는 Keep-Alive에 대한 간접적 인 보증을 제공하므로 AWS로 호스팅하는 경우 Keep-Alive에 의존하는 것이 안전 할 가능성이 높지만 마일리지는 다를 수 있습니다.
안타깝게도 TCP 연결은 OS 수준에서 관리되기 때문에 Java는 .NET과 같은 소켓 수준에서 제한 시간 구성을 지원하지 않습니다 java.net.Socket
. 나는 몇 가지 시도를 발견했다 (3) 이 옵션을 구성 할 네이티브 코드를 호출하는 자바 소켓을 만들 수 있도록 JNI (Java Native Interface)를 사용하지만, 아무도 광범위한 지역 사회의 채택 또는 지원을 가지고있는 것 같습니다 없습니다.
대신 운영 체제 전체에 구성을 적용해야 할 수도 있습니다. 이 구성은 전체 시스템에서 실행되는 모든 TCP 연결에 영향을 미칩니다.
현재 구성된 TCP Keep-Alive 설정은 다음 위치에서 찾을 수 있습니다.
/proc/sys/net/ipv4/tcp_keepalive_time
/proc/sys/net/ipv4/tcp_keepalive_probes
/proc/sys/net/ipv4/tcp_keepalive_intvl
다음과 같이 업데이트 할 수 있습니다.
# Send first Keep-Alive packet when a TCP socket has been idle for 3 minutes
$ echo 180 > /proc/sys/net/ipv4/tcp_keepalive_time
# Send three Keep-Alive probes...
$ echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
# ... spaced 10 seconds apart.
$ echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl
이러한 변경 사항은 다시 시작해도 지속되지 않습니다. 지속적으로 변경하려면 다음을 사용하십시오 sysctl
.
sysctl -w net.ipv4.tcp_keepalive_time=180 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=10
현재 구성된 설정은 다음을 사용하여 볼 수 있습니다 sysctl
.
$ sysctl net.inet.tcp | grep -E "keepidle|keepintvl|keepcnt"
net.inet.tcp.keepidle: 7200000
net.inet.tcp.keepintvl: 75000
net.inet.tcp.keepcnt: 8
참고로, 맥 OS X를 정의 keepidle
하고 keepintvl
초를 사용하는 리눅스에 반대 밀리 초 단위입니다.
sysctl
재부팅시 이러한 설정을 유지하는 속성을 설정할 수 있습니다 .
sysctl -w net.inet.tcp.keepidle=180000 net.inet.tcp.keepcnt=3 net.inet.tcp.keepintvl=10000
또는에 추가 할 수 있습니다 /etc/sysctl.conf
(파일이없는 경우 생성).
$ cat /etc/sysctl.conf
net.inet.tcp.keepidle=180000
net.inet.tcp.keepintvl=10000
net.inet.tcp.keepcnt=3
확인할 Windows 컴퓨터가 없지만 레지스트리에서 각 TCP Keep-Alive 설정을 찾아야합니다.
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters
각주
1. 자세한 내용은를 참조하십시오 man tcp
.
2.이 패킷은 "Keep-Alive"패킷이라고도하지만 TCP 사양 내에서는 일반 ACK
패킷 일뿐 입니다. Wireshark와 같은 응용 프로그램은 소켓의 이전 통신을 참조하여 포함 된 시퀀스 및 승인 번호의 메타 분석을 통해 "Keep-Alive"패킷으로 레이블을 지정할 수 있습니다.
3. 기본 Google 검색에서 찾은 몇 가지 예는 lucwilliams / JavaLinuxNet 및 flonatel / libdontdie 입니다.
$ no -a | grep tcp_keep
명령을 사용하여 조회 할 수 있습니다 .
SO_KEEPALIVE 소켓 옵션을 찾고 있습니다.
자바 소켓 API를 노출하는가 "연결 유지"를 통해 응용 프로그램 setKeepAlive
및 getKeepAlive
방법.
편집 : SO_KEEPALIVE는 "실제"데이터를 보내지 않고 OS 네트워크 프로토콜 스택에서 구현됩니다. 연결 유지 간격은 운영 체제에 따라 다르며 커널 매개 변수를 통해 조정할 수 있습니다.
데이터가 전송되지 않기 때문에 SO_KEEPALIVE는 소켓이 연결된 서비스의 활성 상태가 아닌 네트워크 연결의 활성 상태 만 테스트 할 수 있습니다. 후자를 테스트하려면 서버에 메시지를 보내고 응답을받는 것과 관련된 무언가를 구현해야합니다.
TCP 킵 얼라이브와 HTTP 킵 얼라이브는 매우 다른 개념입니다. TCP에서 keepalive는 부실 연결을 감지하기 위해 전송되는 관리 패킷입니다. HTTP에서 keepalive는 지속적인 연결 상태를 의미합니다.
이것은 TCP 사양에서 가져온 것입니다.
Keep-alive 패킷은 간격 내 연결에 대해 수신 된 데이터 또는 확인 패킷이 없을 때만 전송되어야합니다. 이 간격은 구성 가능해야하며 기본값은 2 시간 이상이어야합니다.
보시다시피 기본 TCP 연결 유지 간격은 대부분의 응용 프로그램에서 너무 깁니다. 애플리케이션 프로토콜에 Keepalive를 추가해야 할 수도 있습니다.
HTTP/1.0
각 요청 / 응답에서 서버에 다시 연결해야했습니다. 들어 HTTP/1.1
그들이 도입 Keep-Alive
이 더 많은 파일을 요청하고 '파이프 라인'을 허용 용이하게 응답을 처리 완료 후 연결을 죽이지에 서버를 실행하는 데 사용할 수있는 헤더를; 여러 요청을 보낸 다음 모든 데이터가 돌아올 때까지 기다립니다.
마스 쿼 레이 딩 NAT를 사용하는 경우 (요즘 대부분의 가정용 사용자가 그렇듯이) 외부 포트 풀이 제한되어 있으며 이러한 포트는 TCP 연결간에 공유되어야합니다. 따라서 위장 NAT는 특정 기간 동안 데이터가 전송되지 않으면 연결이 종료되었다고 가정하는 경향이 있습니다.
이 문제 및 기타 이러한 문제 (두 끝점 사이의 모든 문제)는 합리적인 유휴 기간 후에 데이터를 보내려고하면 연결이 더 이상 "작동"하지 않음을 의미 할 수 있습니다. 그러나 데이터 전송 을 시도 할 때까지이를 발견하지 못할 수 있습니다 .
킵 얼라이브를 사용 하면 연결이 중단 될 가능성이 줄어들고 끊어진 연결에 대해 더 빨리 알 수 있습니다.
다음은 킵 얼라이브에 대한 몇 가지 보충 문헌으로이를 훨씬 더 자세히 설명합니다.
http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO
Java는 실제 연결 유지 시간을 제어하는 것을 허용하지 않기 때문에 Linux 커널 (또는 proc 기반 OS)을 사용하는 경우 예제를 사용하여 변경할 수 있습니다.
JAVA Socket – TCP 연결은 OS 수준에서 관리되며 java.net.Socket은 소켓 수준에서 Keepalive 패킷에 대한 시간 제한을 설정하는 내장 기능을 제공하지 않습니다. 하지만 자바 소켓에 대해 keepalive 옵션을 활성화 할 수는 있지만 오래된 tcp 연결 후 처리하는 데 기본적으로 2 시간 11 분 (7200 초)이 걸립니다. 이 원인 연결은 퍼지하기 전에 매우 오랫동안 사용할 수 있습니다. 그래서 이러한 옵션을 구성하기 위해 네이티브 코드 (c ++)를 호출하는 JNI (Java Native Interface)를 사용하는 몇 가지 솔루션을 찾았습니다.
**** Windows OS ****
Windows 운영 체제에서 keepalive_time 및 keepalive_intvl은 구성 할 수 있지만 tcp_keepalive_probes는 변경할 수 없습니다. 기본적으로 TCP 소켓이 초기화되면 연결 유지 시간 제한이 2 시간으로 설정되고 연결 유지 간격이 1 초로 설정됩니다. Keep-alive 제한 시간의 기본 시스템 전체 값은 밀리 초 단위의 값을 사용하는 KeepAliveTime 레지스트리 설정을 통해 제어 할 수 있습니다.
Windows Vista 이상에서 Keep-alive 프로브 (데이터 재전송) 수는 10으로 설정되며 변경할 수 없습니다.
Windows Server 2003, Windows XP 및 Windows 2000에서 연결 유지 프로브 수의 기본 설정은 5입니다. 연결 유지 프로브 수는 제어 할 수 있습니다. Windows의 경우 Winsock IOCTL 라이브러리는 tcp-keepalive 매개 변수를 구성하는 데 사용됩니다.
int WSAIoctl (SocketFD, // 소켓을 식별하는 설명자 SIO_KEEPALIVE_VALS, // dwIoControlCode (LPVOID) lpvInBuffer, // tcp_keepalive 구조체에 대한 포인터 (DWORD) cbInBuffer, // 입력 버퍼 길이 NULL, // 출력 버퍼 0, // 크기 출력 버퍼 (LPDWORD) lpcbBytesReturned, // 반환 된 바이트 수 NULL, // OVERLAPPED 구조체 NULL // 완료 루틴);
Linux OS
Linux는이를 사용하기 위해 TCP / IP 네트워킹을 활성화해야하는 킵 얼라이브에 대한 지원이 내장되어 있습니다. 프로그램은 setsockopt 인터페이스를 사용하여 소켓에 대한 연결 유지 제어를 요청해야합니다.
int setsockopt (int 소켓, int 레벨, int optname, const void * optval, socklen_t optlen)
각 클라이언트 소켓은 java.net.Socket을 사용하여 생성됩니다. 각 소켓의 파일 설명자 ID는 Java 리플렉션을 사용하여 검색합니다.
Microsoft Docs 에 따른 Windows의 경우