윈도우 응용 프로그램의 Socket 연결 시 time-out 시간 제어
일단 기본적인 제어는,
Which is the default TCP connect timeout in Windows?
; https://serverfault.com/questions/193160/which-is-the-default-tcp-connect-timeout-in-windows
Appendix A: TCP/IP Configuration Parameters
; https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc739819(v=ws.10)
TcpInitialRTT: Defines what the initial time-out settings are for new connections. This number in seconds is doubled each time it retransmits before timing a connection out. Defaults to 3.
TcpMaxConnectRetransmissions: Defines the number of retransmissions before timing a connection out. Defato 5.
How to set TCP/IP abort interval or timeout in Windows XP?
; https://superuser.com/questions/339959/how-to-set-tcp-ip-abort-interval-or-timeout-in-windows-xp
TcpInitialRTT, TcpMaxConnectRetransmissions 관련 값들을 통해 이뤄집니다. 그런데 이게 윈도우 서버 2008 R2/7까지는 레지스트리 설정(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters)으로 가능한 반면, 2012를 기점으로 netsh 관리로 통합이 됩니다.
테스트를 간단하게 만들기 위해 최신 버전 기준인 Windows Server 2019에서 TcpInitialRTT, TcpMaxConnectRetransmissions 값을 다음의 명령어로 구할 수 있고,
C:\Windows\system32> netsh interface tcp show global
Querying active state...
TCP Global Parameters
----------------------------------------------
Receive-Side Scaling State : enabled
Chimney Offload State : automatic
NetDMA State : enabled
Direct Cache Acess (DCA) : disabled
Receive Window Auto-Tuning Level : normal
Add-On Congestion Control Provider : none
ECN Capability : disabled
RFC 1323 Timestamps : disabled
Initial RTO : 3000
Non Sack Rtt Resiliency : disabled
Max SYN Retransmissions : 2
** The above autotuninglevel setting is the result of Windows Scaling heuristics
overriding any local/policy configuration on at least one profile.
해당 값들의 변경은 이런 식으로 할 수 있습니다.
C:\Windows\system32> netsh interface tcp set global MaxSynRetransmissions=2
Ok.
C:\Windows\system32> netsh interface tcp set global InitialRto=1000
Ok.
그럼, 실제로 Socket 코드를 다음과 같이 작성하고,
using (Socket clntSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
var entry = Dns.GetHostEntry(target);
clntSock.Connect(new IPEndPoint(entry.AddressList[0], port));
}
기본 값 상태에서,
TcpInitialRTT == 3000
TcpMaxConnectRetransmissions == 2
외부 인터넷 망에 있는 서버를 대상으로 listening하지 않는 포트에 대해 테스트를 해보면 21초가 걸리는 것을 확인할 수 있습니다.
c:\temp> ConsoleApp1.exe www.sysnet.pe.kr 8032
21203.2789
21초가 걸린 이유는 계산 결과와,
RTO: 3000 = 3초
1번 재시도: 3000 * 2 = 6초
2번 재시도: 6000 * 2 = 12초
-------------------------------
총 21초
일치합니다. 그럼, 설정값을 변경도 해봐야겠지요. ^^
TcpInitialRTT == 2000
TcpMaxConnectRetransmissions == 2
RTO: 3000 = 2초
1번 재시도: 2000 * 2 = 4초
2번 재시도: 4000 * 2 = 8초
-------------------------------
총 14초
실행해 보면,
c:\temp>ConsoleApp1.exe
14042.6988
예상했던 데로, 대략 14초(14000ms)가 걸렸습니다.
참고로, TcpInitialRTT, TcpMaxConnectRetransmissions 값을 조절하다 보면 Connection Timeout 시간이 지나치게 오래 걸릴 수 있는데,
TcpInitialRTT == 3000
TcpMaxConnectRetransmissions == 5
RTO: 3000 = 3초
1번 재시도: 3000 * 2 = 6초
2번 재시도: 6000 * 2 = 12초
3번 재시도: 12000 * 2 = 24초
4번 재시도: 24000 * 2 = 48초
5번 재시도: 48000 * 2 = 96초
-------------------------------
총 189초
정작 실행해 보면 100초 정도에 끝납니다.
c:\temp>ConsoleApp1.exe
100058.9233
왜냐하면, 최댓값이 100초이기 때문입니다. 관련해서 다음의 Q&A를 보면,
Window registy: TCPMaxConnectRetransmissions
; https://social.technet.microsoft.com/Forums/windows/en-US/110271d5-5221-44b4-af14-f07f3fa01a73/window-registy-tcpmaxconnectretransmissions?forum=w7itpronetworking
Windows 2003에서는 최댓값이 120초라고 하니 이것 역시 윈도우 버전마다 다를 수 있습니다.
경험상, 이와 관련된 값들을 굳이 설정해야 한다면 반드시 해당 환경에서 테스트를 해보는 것이 좋습니다. 일례로 예전에 소개했던 장애 환경의 경우,
.NET Remoting에서 서비스 호출 시 SYN_SENT로 남는 현상
; https://www.sysnet.pe.kr/2/0/11998
원인은 알 수 없었지만 일단 TcpInitialRTT, TcpMaxConnectRetransmissions 레지스트리 값을 조정한 경우 연결 시간은 제어가 되었는데 - 즉, SYN_SENT로 남는 시간을 제어할 수 있었지만 아쉽게도 시스템이 일정 시간 동작한 후에는 다시 무한대의 time-out 시간으로 바뀌는 현상이 발생했습니다. 일단 그런 경우도 있다는 것을 알아만 두시고. ^^
그 외에, maxsynretransmissions과 initialrto에 설정 가능한 값의 범위는 netsh 도움말에 나옵니다.
C:\> netsh interface tcp set global ?
Usage: set global [[rss=]disabled|enabled|default]
[[autotuninglevel=]
disabled|highlyrestricted|restricted|normal|experimental]
[[congestionprovider=]none|ctcp|default]
[[ecncapability=]disabled|enabled|default]
[[timestamps=]disabled|enabled|default]
[[initialrto=]<300-3000>]
[[rsc=]disabled|enabled|default]
[[nonsackrttresiliency=]disabled|enabled|default]
[[maxsynretransmissions=]<2-8>]
[[fastopen=]disabled|enabled|default]
[[fastopenfallback=]disabled|enabled|default]
[[hystart=]disabled|enabled|default]
[[pacingprofile=]off|initialwindow|slowstart|always|default]
...[생략]...
기타... Windows Server 2008 R2 이하에서는 "netsh interface tcp show global" 명령어의 출력이 다음과 같습니다.
C:\Windows\system32> netsh interface tcp show global
Querying active state...
TCP Global Parameters
----------------------------------------------
Receive-Side Scaling State : enabled
Chimney Offload State : disabled
Receive Window Auto-Tuning Level : disabled
Add-On Congestion Control Provider : ctcp
ECN Capability : disabled
RFC 1323 Timestamps : disabled
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]