TCP 소켓 연결에 "연결 유지"가 있습니까?
HTTP 연결 유지에 대해 들어 봤지만 지금은 원격 서버와 소켓 연결을 열고 싶습니다.
이제이 소켓 연결이 영원히 열려 있거나 HTTP 연결 유지와 유사한 시간 제한이 있습니까?
TCP 소켓은 닫힐 때까지 열려 있습니다.
즉, 실제로 데이터를 전송하지 않고 끊어진 연결 (라우터에서 끊어진 것과 같이 끊어짐 등)을 실제로 데이터를 전송하지 않고 감지하는 것은 매우 어렵 기 때문에 대부분의 응용 프로그램은 확인하기 위해 자주 일종의 핑 / 퐁 반응을 수행합니다. 연결은 실제로 살아 있습니다.
이제이 소켓 연결이 영원히 열려 있거나 HTTP 연결 유지와 유사한 시간 제한이 있습니까?
짧은 대답은 yes 입니다. 타임 아웃이 있으며 TCP Keep-Alive를 통해 적용됩니다.
Keep-Alive 시간 제한을 구성하려면 아래의 "TCP 시간 제한 변경"섹션을 참조하십시오.
소개
TCP 연결은 연결의 각 끝에 하나씩 두 개의 소켓으로 구성됩니다. 한 쪽이 연결을 종료하려고 할 때 RST
다른 쪽이 확인하고 모두 소켓을 닫는 패킷을 보냅니다 .
그러나 그렇게 될 때까지 양측은 소켓을 무기한으로 열어 둡니다. 이렇게하면을 통해 다른 쪽 끝에 알리지 않고 의도적으로 또는 일부 오류로 인해 한쪽이 소켓을 닫을 가능성이 있습니다 RST
. 이 시나리오를 감지하고 오래된 연결을 닫으려면 TCP Keep Alive 프로세스가 사용됩니다.
Keep-Alive 프로세스
Keep-Alives 작동 방식을 결정하는 세 가지 구성 가능한 속성이 있습니다. Linux에서는 1입니다 .
tcp_keepalive_time
- 기본 7200 초
tcp_keepalive_probes
- 기본값 9
tcp_keepalive_intvl
- 기본 75 초
프로세스는 다음과 같이 작동합니다.
- 클라이언트가 TCP 연결을 엽니 다.
- 연결이
tcp_keepalive_time
몇 초 동안 침묵 하면 하나의 빈ACK
패킷을 보냅니다 . 1 - 서버
ACK
가 자체적으로 응답 했습니까 ?- 아니
tcp_keepalive_intvl
몇 초 동안 기다린 다음 다른 메시지를 보냅니다ACK
ACK
전송 된 프로브 수가 같을 때까지 반복하십시오tcp_keepalive_probes
.- 이 시점에서 응답이 수신되지 않으면 a를 보내고
RST
연결을 종료하십시오.
- 예 : 2 단계로 돌아갑니다.
- 아니
이 프로세스는 대부분의 운영 체제에서 기본적으로 활성화되어 있으므로 다른 쪽 끝이 2 시간 11 분 (7200 초 + 75 * 9 초) 동안 응답하지 않으면 작동하지 않는 TCP 연결이 정기적으로 정리됩니다.
Gotchas
2 시간 기본값
연결이 기본적으로 2 시간 동안 유휴 상태가 될 때까지 프로세스가 시작되지 않기 때문에 부실 TCP 연결은 정리되기 전에 매우 오랫동안 지속될 수 있습니다. 이는 데이터베이스 연결과 같은 값 비싼 연결에 특히 해로울 수 있습니다.
Keep-Alive는 선택 사항입니다.
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 시간 초과 변경
소켓 당
안타깝게도 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
맥 OS X
현재 구성된 설정은 다음을 사용하여 볼 수 있습니다 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
윈도우
I don't have a Windows machine to confirm, but you should find the respective TCP Keep-Alive settings in the registry at
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters
Footnotes
1. See man tcp
for more information.
2. This packet is often referred to as a "Keep-Alive" packet, but within the TCP specification it is just a regular ACK
packet. Applications like Wireshark are able to label it as a "Keep-Alive" packet by meta-analysis of the sequence and acknowledgement numbers it contains in reference to the preceding communications on the socket.
3. Some examples I found from a basic Google search are lucwilliams/JavaLinuxNet and flonatel/libdontdie.
You are looking for the SO_KEEPALIVE socket option.
The Java Socket API exposes "keep-alive" to applications via the setKeepAlive
and getKeepAlive
methods.
EDIT: SO_KEEPALIVE is implemented in the OS network protocol stacks without sending any "real" data. The keep-alive interval is operating system dependent, and may be tuneable via a kernel parameter.
Since no data is sent, SO_KEEPALIVE can only test the liveness of the network connection, not the liveness of the service that the socket is connected to. To test the latter, you need to implement something that involves sending messages to the server and getting a response.
TCP keepalive and HTTP keepalive are very different concepts. In TCP, the keepalive is the administrative packet sent to detect stale connection. In HTTP, keepalive means the persistent connection state.
This is from TCP specification,
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval. This interval MUST be configurable and MUST default to no less than two hours.
As you can see, the default TCP keepalive interval is too long for most applications. You might have to add keepalive in your application protocol.
If you're behind a masquerading NAT (as most home users are these days), there is a limited pool of external ports, and these must be shared among the TCP connections. Therefore masquerading NATs tend to assume a connection has been terminated if no data has been sent for a certain time period.
This and other such issues (anywhere in between the two endpoints) can mean the connection will no longer "work" if you try to send data after a reasonble idle period. However, you may not discover this until you try to send data.
Using keepalives both reduces the chance of the connection being interrupted somewhere down the line, and also lets you find out about a broken connection sooner.
Here is some supplemental literature on keepalive which explains it in much finer detail.
http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO
Since Java does not allow you to control the actual keepalive times, you can use the examples to change them if you're using a Linux kernel (or proc based OS).
In JAVA Socket – TCP connections are managed on the OS level, java.net.Socket does not provide any in-built function to set timeouts for keepalive packet on a per-socket level. But we can enable keepalive option for java socket but it takes 2 hours 11 minutes (7200 sec) by default to process after a stale tcp connections. This cause connection will be availabe for very long time before purge. So we found some solution to use Java Native Interface (JNI) that call native code(c++) to configure these options.
****Windows OS****
In windows operating system keepalive_time & keepalive_intvl can be configurable but tcp_keepalive_probes cannot be change.By default, when a TCP socket is initialized sets the keep-alive timeout to 2 hours and the keep-alive interval to 1 second. The default system-wide value of the keep-alive timeout is controllable through the KeepAliveTime registry setting which takes a value in milliseconds.
On Windows Vista and later, the number of keep-alive probes (data retransmissions) is set to 10 and cannot be changed.
On Windows Server 2003, Windows XP, and Windows 2000, the default setting for number of keep-alive probes is 5. The number of keep-alive probes is controllable. For windows Winsock IOCTLs library is used to configure the tcp-keepalive parameters.
int WSAIoctl( SocketFD, // descriptor identifying a socket SIO_KEEPALIVE_VALS, // dwIoControlCode (LPVOID) lpvInBuffer, // pointer to tcp_keepalive struct (DWORD) cbInBuffer, // length of input buffer NULL, // output buffer 0, // size of output buffer (LPDWORD) lpcbBytesReturned, // number of bytes returned NULL, // OVERLAPPED structure NULL // completion routine );
Linux OS
Linux has built-in support for keepalive which is need to be enabling TCP/IP networking in order to use it. Programs must request keepalive control for their sockets using the setsockopt interface.
int setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)
Each client socket will be created using java.net.Socket. File descriptor ID for each socket will retrieve using java reflection.
For Windows according to Microsoft docs
- KeepAliveTime (REG_DWORD, milliseconds, by default is not set which means 7,200,000,000 = 2 hours) - analogue to tcp_keepalive_time
- KeepAliveInterval (REG_DWORD, milliseconds, by default is not set which means 1,000 = 1 second) - analogue to tcp_keepalive_intvl
- Since Windows Vista there is no analogue to tcp_keepalive_probes, value is fixed to 10 and cannot be changed
참고URL : https://stackoverflow.com/questions/1480236/does-a-tcp-socket-connection-have-a-keep-alive
'program story' 카테고리의 다른 글
Oracle Database 11g에서 새 스키마 / 새 사용자를 생성하는 방법은 무엇입니까? (0) | 2020.10.13 |
---|---|
Lollipop 충돌 전 Android 벡터 드로어 블 사용 (0) | 2020.10.13 |
빌드 버전에 따라 앱 이름이 다르나요? (0) | 2020.10.13 |
Windows 8 및 10에서 npm 경로 수정 (0) | 2020.10.13 |
Android 앱 리소스에서 JSON 파일 사용 (0) | 2020.10.13 |