수정 이력(7건, 최종 수정 2026년 09월 03일)
이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.
- permalink·저자 표기·지식 맵 래퍼·깨진 내부 링크 등 CI가 지적한 표시용 수정을 반영했습니다. 본문의 기술적인 주장은 바꾸지 않았습니다.
- 일본어 원문의 완역으로 다시 번역했습니다. 기존 한국어판은 원문의 일부만 옮긴 축약본이라 절, 표, Mermaid 그림, 그림 설명, FAQ가 빠져 있었습니다. 일본어 원문에 맞춰 이들을 모두 복원했고, 기술적인 주장은 일본어판과 같습니다.
- 원인 분리 순서와 RTO가 되돌아오는 구조를 그림으로도 따라갈 수 있도록 Mermaid 그림을 10개 추가했습니다(본문 500~750자당 1그림 규약에 맞춘 것입니다). 기존 그림에는 일련번호가 붙은 캡션을 달았습니다. 본문 문장은 바꾸지 않았습니다.
- 기사 맨 앞에 '이 기사의 지식 맵' 절을 추가했습니다. 본문에서 다루는 개념과 그 관계를 요약·그림·상세 페이지 링크로 정리한 것입니다. 본문의 주장은 바꾸지 않았습니다.
- 외부 리뷰(1283건)에 대한 대응으로 본문을 갱신했습니다. 개별 변경 내용은 아래 이력을 참조하십시오.
- 타임스탬프를 켜는 구체 절차를 추가했습니다(`netsh`와 PowerShell의 `Set-NetTCPSetting`, 레지스트리의 `Tcp1323Opts`, 신규 연결부터만 효과가 있다는 주의 3점 등). 용어표를 추가하고, RTO의 하한은 타임스탬프 유무로 바뀌지 않음을 명시한 뒤, 실제로 효과가 있는 흐름(백오프한 RTO가 새로운 RTT 측정으로 되돌아온다, 그 측정은 재전송하지 않은 세그먼트에서만 얻을 수 있다)을 설명했습니다. Wireshark 화면에서 무엇이 어떻게 보이는지의 표도 추가했습니다.
- 참고 링크 등에서 세로줄(파이프) 기호가 들어간 줄이 표로 표시되어 링크를 누를 수 없었던 표시 오류를 수정했습니다. 본문 내용은 그대로입니다.
- 최초 공개
이 글을 인용하기(DOI: 10.5281/zenodo.21635104)
이 글은 Zenodo에 보관되어 있습니다. 항상 최신 버전으로 연결되는 DOI와 지금 보고 있는 버전에 고정된 DOI를 아래에 함께 제시합니다.
Go Komura (2026). 「TCP 재전송으로 산업용 카메라 통신이 멈추는 원인 분리」. 합동회사 코무라소프트. https://doi.org/10.5281/zenodo.21635104 https://comcomponent.com/ko/blog/tcp-retransmission-rfc1323-industrial-camera/
- DOI(최신 버전)
- 10.5281/zenodo.21635104
- DOI(이 버전)
- 10.5281/zenodo.22217418
산업용 카메라나 장치 제어 통신에서는, 평균적으로는 빠른데도 가끔 수 초 멈추는 현상이 가장 까다롭습니다. 재현율이 낮고 평소에는 아무 일도 일어나지 않으므로, UI, 스레드, GC, 카메라 SDK, NIC, 스위치 전부가 조금씩 의심스러워집니다.
이번에 다루는 것은 산업용 카메라를 제어하는 앱과 호스트의 TCP 통신에서, 드물게 수 초간만 통신이 멈추는 현상입니다. 조사해 보니 정체는 앱의 정지가 아니라 패킷 로스에 기인한 TCP의 재전송 대기였습니다. 또한 RFC1323 계열의 타임스탬프 기능(현재의 정리로는 RFC 7323)을 켜면, 이 환경에서는 대기 시간을 최소한으로 줄일 수 있었습니다.
장치명이나 구성, 수치는 일반화했지만, 사고방식은 그대로 실무에서 쓸 수 있습니다.
목차
- 먼저 결론(한 마디로)
- 증상이 나타나는 모습
- 2.1. 앱은 살아 있는데 응답만 수 초 멈춘다
- 2.2. 발생 빈도가 낮아 로그만으로는 보이기 어렵다
- 무엇이 일어나고 있었는가(그림)
- 3.1. 패킷 로스에서 재전송 대기로 들어간다
- 3.2. 초 단위 정지와 RTO의 형태가 맞았다
- 조사에서 본 포인트
- 4.1. 먼저 앱 안의 정지 요인을 제외한다
- 4.2. 패킷 캡처로 재전송을 확인한다
- 4.3. 협상된 TCP 옵션을 본다
- RFC1323 타임스탬프가 효과가 있는 이유
- 5.1. 타임스탬프는 RTTM과 PAWS를 위한 것
- 5.2. 재전송 시 RTT 측정의 모호함을 제거할 수 있다
- 5.3. 이 사례에서 대기 시간을 줄일 수 있었던 이유
- 실제로 한 대책
- 6.1. 타임스탬프를 켠다
- 6.2. SYN / SYN-ACK에서 TSopt를 확인한다
- 6.3. 그래도 효과가 없을 때 볼 곳
- Wireshark에서 볼 포인트
- 대략적인 구분
- 정리
- 참고 자료
이 글의 지식 맵
산업용 카메라 제어 앱에서 드물게 수 초 동안만 통신이 멈추는 원인을 가려낸 글입니다. 원인은 앱의 정지가 아니라, 패킷 로스로 인해 ACK가 돌아오지 않아 TCP가 재전송 타이머(RTO)의 만료를 기다리는 재전송 대기였습니다. RTO는 초기값 1초를 기준으로 실패할 때마다 배증되므로, 조건이 나쁘면 수 초 단위의 정지로 보입니다. TCP 타임스탬프 옵션(RFC1323/RFC7323)을 활성화하면 Karn의 알고리즘이 금지하는 재전송 세그먼트로부터의 RTT 측정이라는 제약을 없애, RTO가 과도하게 보수적인 상태로 남는 시간을 줄일 수 있지만, 패킷 로스 자체를 없애는 구조는 아닙니다. Wireshark로 재전송과 대기 시간을 확인하고, SYN/SYN-ACK에서 TSopt 협상을 확인하는 것이 원인 구분의 기본이 됩니다.
flowchart LR
accTitle: TCP 재전송과 RFC1323 타임스탬프
accDescr: 패킷 로스가 TCP 재전송과 RTO 대기를 일으켜 수 초간 통신이 멈춘 것처럼 보이는 것, TCP 타임스탬프 옵션이 Karn의 알고리즘이 정한 제약을 없애 재전송 시 RTT 측정의 모호함을 줄이는 것, Wireshark로 확인하는 절차와의 관계를 보여주는 그림
tcp_retransmission["TCP 재전송(TCP Retransmission)"]
tcp_rto["RTO(재전송 타이머)"]
tcp_timestamps_option["TCP 타임스탬프 옵션"]
packet_loss["패킷 손실"]
tcp_rtt["RTT(왕복 시간)"]
intermittent_communication_stall["간헐적인 수 초간 통신 중단"]
wireshark["Wireshark"]
rttm["RTTM(왕복 시간 측정)"]
paws["PAWS(시퀀스 번호 순환 방지)"]
karn_algorithm["Karn 알고리즘"]
retransmission_rtt_ambiguity["재전송 시 RTT 측정의 모호성"]
fast_retransmit["fast retransmit(고속 재전송)"]
duplicate_ack["Duplicate ACK(중복 ACK)"]
tcp_handshake["TCP 3-way handshake"]
windows_tcp_timestamp_setting["Windows TCP 타임스탬프 설정"]
packet_loss -->|"원인이 될 수 있다"| tcp_retransmission
tcp_retransmission -.->|"전제로 한다"| tcp_rto
tcp_rto -->|"이용한다"| tcp_rtt
tcp_retransmission -->|"원인이 될 수 있다"| intermittent_communication_stall
intermittent_communication_stall -->|"에서 확인할 수 있다"| wireshark
tcp_retransmission -->|"에서 확인할 수 있다"| wireshark
packet_loss -->|"에서 확인할 수 있다"| wireshark
tcp_timestamps_option -->|"이용한다"| rttm
tcp_timestamps_option -->|"이용한다"| paws
karn_algorithm -->|"완화한다"| retransmission_rtt_ambiguity
tcp_timestamps_option -->|"완화한다"| retransmission_rtt_ambiguity
tcp_timestamps_option -.->|"완화한다"| intermittent_communication_stall
fast_retransmit -.->|"방지한다"| tcp_rto
fast_retransmit -->|"전제로 한다"| duplicate_ack
packet_loss -->|"원인이 될 수 있다"| duplicate_ack
tcp_timestamps_option -->|"전제로 한다"| tcp_handshake
tcp_timestamps_option -.->|"에서 구성할 수 있다"| windows_tcp_timestamp_setting
windows_tcp_timestamp_setting -->|"에서 확인할 수 있다"| wireshark
tcp_rto -->|"이용한다"| karn_algorithm
그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 19건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle
1. 먼저 결론(한 마디로)
- 드물게 수 초 멈추는 TCP 통신은, 앱 정지가 아니라 패킷 로스 후의 재전송 대기가 정체인 경우가 있습니다
- 패킷 캡처에서
Retransmission과 큰 시간 차가 보이고, 정지 시간이 RTO의 대기 방식과 맞물리면 꽤 의심스럽습니다 - TCP timestamps option은 RTT 측정과 PAWS를 위한 메커니즘으로, 재전송 시 RTT 측정의 모호함도 제거할 수 있습니다
- 이 사례에서는 RFC1323 계열의 타임스탬프 기능을 켜서, RTO 추정이 오래되고 보수적인 채로 남는 시간을 줄여 초 단위의 정지를 최소한으로 줄일 수 있었습니다
- 다만 이것은 로스 자체를 없애는 마법은 아닙니다. 물리 계층, NIC, 스위치, 중간 기기, 드라이버, 버퍼 설계의 재검토는 따로 필요합니다
요컨대, ‘가끔 수 초 멈춘다’의 정체가 TCP 안의 대기 시간이라면, 앱의 재시도만 열심히 해도 핵심을 빗나갑니다. 먼저 wire를 보고 재전송 대기인지 아닌지를 확정하는 편이 빠릅니다.
flowchart TB
accTitle: 이 기사의 결론 흐름
accDescr: 드물게 수 초 멈추는 TCP 통신은 먼저 wire를 보고 재전송 대기인지를 확정하고, 재전송 대기라면 timestamps로 대기 시간을 줄일 수 있는 경우가 있지만, 패킷 로스 자체의 조사는 따로 필요함을 나타낸다.
sym["드물게 수 초 멈추는 TCP 통신"] --> wire["먼저 wire를 본다"]
wire --> conf["재전송 대기인지를 확정한다"]
conf -.-> ts["timestamps로 대기를 줄일 수 있는 경우 있음"]
conf -.-> loss["로스 원인의 조사는 따로 필요"]
그림1: 앱의 재시도를 열심히 하기 전에, 먼저 wire로 ‘어디서 기다리고 있는지’를 맞춘다.
이 다음부터 TCP 약어가 이어집니다. 네트워크가 전문이 아닌 Windows 개발자를 위해 먼저 모아 둡니다. 여기만 잡아 두면, 이후는 막히지 않을 것입니다.
| 용어 | 정식명 | 의미 |
|---|---|---|
| ACK | Acknowledgment | 확인 응답. ‘여기까지 받았다’를 상대에게 알리는 메커니즘입니다 |
| RTT | Round-Trip Time | 왕복 시간. 보낸 뒤 ACK가 돌아올 때까지의 시간입니다 |
| RTO | Retransmission Timeout | 재전송 타이머. 이 시간 안에 ACK가 돌아오지 않으면 재전송합니다. RTT의 추정값에서 계산됩니다 |
| RTTM | Round-Trip Time Measurement | RTT의 측정. 타임스탬프 기능의 목적 중 하나입니다 |
| PAWS | Protect Against Wrapped Sequences | 시퀀스 번호가 한 바퀴 돌아버리는 사고에 대한 대책. 타임스탬프 기능의 또 하나의 목적입니다 |
| TSopt | TCP Timestamps Option | TCP 헤더에 붙는 옵션 중 하나. kind 8, 길이 10바이트로, 다음 2개의 값을 실어 나릅니다 |
| TSval | Timestamp Value | 송신 측이 넣는, 자기 쪽 시계의 값입니다 |
| TSecr | Timestamp Echo Reply | 받은 TSval을 그대로 돌려보내는 칸. 이것으로 ‘어느 송신에 대한 ACK인지’를 알 수 있습니다 |
| SACK | Selective Acknowledgment | 수신 측이 ‘어느 범위를 받았는지’를 개별적으로 전하는 메커니즘입니다 |
| Dup ACK | Duplicate ACK | 같은 시퀀스 번호를 가리키는 ACK가 중복되어 돌아오는 것. 중간에 빠짐이 있다는 신호입니다 |
| fast retransmit | — | Dup ACK가 일정 수 모이면, RTO 만료를 기다리지 않고 재전송하는 메커니즘. Windows의 기본값은 ‘같은 시퀀스 번호의 ACK를 3개(처음 1개와 중복 2개) 받으면’입니다 |
| Karn의 알고리즘 | — | 재전송한 세그먼트에서는 RTT 샘플을 취해서는 안 된다는 규칙. 어느 송신에 대한 ACK인지 모르기 때문입니다 |
2. 증상이 나타나는 모습
2.1. 앱은 살아 있는데 응답만 수 초 멈춘다
처음에 까다로운 것은, 앱 전체가 굳은 것처럼은 보이지 않는다는 점입니다.
- UI는 완전히 죽어 있지 않다
- 프로세스도 죽지 않았다
- CPU 사용률도 치솟지 않았다
- 다만, 카메라 제어 커맨드의 응답만 가끔 수 초 빠진다
이런 증상은 앱 안의 deadlock이나 무한 루프와도 구별하기 어렵습니다. 게다가 장치 제어에서는 1회의 수 초 정지가 그대로 라인 정지의 인상이 됩니다. 평균값이 깨끗해도, 현장의 체감은 꽤 나쁩니다.
2.2. 발생 빈도가 낮아 로그만으로는 보이기 어렵다
이런 유형의 문제가 까다로운 것은, 발생 빈도가 낮다는 점입니다. 한 시간에 한 번, 반나절에 한 번, 조건이 겹쳤을 때만 그런 식으로 나타납니다.
로그만으로 쫓아가면, 대체로 이렇게 됩니다.
- 앱 로그상은 ‘송신했다’ ‘돌아오지 않는다’로 멈춘다
- 수신 측 로그는 ‘아무것도 오지 않았다’로 보인다
- 마침 같은 시간대에 다른 이벤트도 일어나, 범인이 흩어진다
이럴 때 앱 로그만으로 인과관계를 복원하려 하면, 꽤 평범하게 수렁에 빠집니다. 통신 계층까지 한 단계 내려가는 편이 빠릅니다.
flowchart TB
accTitle: 로그만으로는 범인이 정해지지 않는 구도
accDescr: 앱 로그는 송신했지만 돌아오지 않아 멈추고, 수신 측 로그는 아무것도 오지 않은 것처럼 보이며, 같은 시간대의 다른 이벤트로 범인이 흩어지므로, 앱 로그만으로 인과를 복원하려 하지 말고 통신 계층까지 내려가는 편이 빠름을 나타낸다.
l1["앱 로그:송신했지만 돌아오지 않음"] --> lost["범인이 흩어져 수렁에 빠진다"]
l2["수신 측 로그:아무것도 오지 않음"] --> lost
l3["같은 시간대의 다른 이벤트"] -.-> lost
lost --> down["통신 계층까지 한 단계 내려간다"]
그림2: 발생 빈도가 낮은 정지는 로그만으로 쫓으면 수렁에 빠진다. 패킷으로 보는 편이 빠르다.
3. 무엇이 일어나고 있었는가(그림)
3.1. 패킷 로스에서 재전송 대기로 들어간다
이번 원인 흐름은 단순합니다. 중간 어딘가에서 패킷이 손실되고, 송신 측이 ACK를 기다리다가, 오지 않으니 RTO를 기다린 뒤 재전송하고 있었습니다.
sequenceDiagram
participant Host as 호스트 앱
participant Net as 네트워크
participant Cam as 카메라 측
Host->>Net: 제어 커맨드 (Seq=N)
Note over Net: 여기서 로스
Note over Host: ACK가 오지 않아 기다린다
Note over Host: 이 요청의 회복에는 RTO 대기가 들어간다
Host->>Net: 제어 커맨드를 재전송
Net->>Cam: 재전송 패킷 도달
Cam-->>Net: ACK
Net-->>Host: ACK
Note over Host: 여기서 통신 재개
그림3: 패킷이 손실되면 ACK가 돌아오지 않고, RTO 만료를 기다린 뒤 재전송한다. 앱에는 이 사이가 ‘수 초의 정지’로 보인다.
앱에서 보면 ‘수 초 멈춘’ 것처럼 보이지만, TCP 입장에서는 ‘아직 ACK가 오지 않아, 재전송 타이머 만료를 기다리고 있었다’는 것뿐입니다. 눈에 띄지 않지만, 이런 정지 방식은 흔합니다.
이번 제어 통신은 작은 request/response가 많고, 한 번의 주고받기로 대량의 ACK되지 않은 데이터가 날아가지 않았습니다. 그래서 duplicate ACK를 충분히 모아 fast retransmit에 올라타기보다 먼저, RTO 대기가 표면에 나오기 쉬운 구성이었습니다.
flowchart TB
accTitle: 제어 통신에서 RTO 대기가 표면에 나오기 쉬운 이유
accDescr: 작은 request/response 중심의 제어 통신에서는 미 ACK 데이터가 적고, duplicate ACK가 충분히 모이지 않아 fast retransmit에 올라타기 어려우므로, 그 결과 RTO 대기가 표면에 나오기 쉬움을 나타낸다.
small["작은 request/response 중심"] --> few["ACK되지 않은 데이터가 적다"]
few --> nodup["Dup ACK가 충분히 모이지 않는다"]
nodup --> nofr["fast retransmit에 올라타기 어렵다"]
nofr --> rto["RTO 대기가 표면에 나온다"]
그림4: 대량의 데이터가 흐르는 통신과 달리, 제어 통신의 로스는 RTO 만료 대기가 되기 쉽다.
3.2. 초 단위 정지와 RTO의 형태가 맞았다
TCP의 재전송 대기는 구현 차이는 있어도, 보수적으로 기다립니다. RFC 6298에서는 초기 RTO는 1초가 기준이며, 계산 결과가 그보다 작으면 1초로 올림하고, 타임아웃이 일어나면 배증합니다.
flowchart LR
A[패킷 로스] --> B[ACK가 오지 않는다]
B --> C[RTO 대기]
C --> D[재전송]
D --> E{ACK가 돌아오는가?}
E -- 예 --> F[통신 재개]
E -- 아니오 --> G[RTO를 배증]
G --> C
그림5: RTO는 ACK가 돌아오지 않을 때마다 배증한다. 1초·2초·4초라는 대기 방식은 이 형태에서 온다.
그래서, 수백 밀리초로 끝났으면 하는 상황에서도, 조건이 나쁘면 1초, 2초, 4초처럼 기다리게 보일 수 있습니다. 이번의 ‘드물게 수 초 멈춘다’는 이 형태와 꽤 그대로 맞물려 있었습니다.
4. 조사에서 본 포인트
4.1. 먼저 앱 안의 정지 요인을 제외한다
처음부터 TCP라고 단정하지 않고, 먼저 앱 측의 전형적인 요인을 제외했습니다.
| 확인한 것 | 본 이유 | 이번의 결론 |
|---|---|---|
| UI 스레드 / 워커 스레드 | hang이나 상호 대기의 확인 | 주원인은 아니었다 |
| CPU 사용률 | 고부하에 의한 처리 지연의 확인 | 정지 시에도 CPU가 치솟지 않았다 |
| GC / 메모리 압박 | 일시 정지의 확인 | 정지 시간의 형태가 맞지 않았다 |
| 카메라 SDK 호출 | SDK 안 대기의 확인 | wire상의 지연과 일치하지 않았다 |
| 패킷 캡처 | 통신 계층의 재전송 확인 | 여기서 원인의 흐름이 보였다 |
여기서 중요한 것은, 앱 로그의 시각만으로 범인을 정하지 않는 것입니다. 장치 제어 앱에서는, 상위 대기가 하위 대기를 그대로 비추고 있는 경우가 있습니다.
flowchart TB
accTitle: 앱 안 요인을 먼저 제외하는 원인 분리 순서
accDescr: 처음부터 TCP라고 단정하지 않고, 스레드나 CPU나 GC나 카메라 SDK 같은 앱 안의 전형적인 정지 요인을 먼저 제외한 뒤, 패킷 캡처로 통신 계층의 재전송을 확인하는 원인 분리 순서를 나타낸다.
app["스레드·CPU·GC·SDK를 먼저 제외한다"] --> cap["패킷 캡처로 통신 계층을 본다"]
cap --> found["재전송의 흐름이 보이기 시작한다"]
app -.-> warn["로그의 시각만으로 범인을 정하지 않는다"]
그림6: 단정하지 않는다. 앱 안의 전형 요인을 제외한 뒤, wire로 내려간다.
4.2. 패킷 캡처로 재전송을 확인한다
패킷 캡처를 취해 보면, 정지하고 있는 시간대에서 TCP Retransmission이 보이고, 게다가 그 직전에 ACK가 돌아오지 않았음이 드러났습니다.
봐야 할 점은 이 부근입니다.
- 같은
Seq의 재전송이 나오고 있는가 - 재전송까지의 시간 차가 정지 시간과 일치하는가
Dup ACK나Fast Retransmission이 아니라, RTO 만료 대기로 보이는가- 문제의 연결이 매번 같은
tcp.stream에 나오는가
여기가 맞으면, ‘앱이 멈춰 있는’ 것이 아니라 ‘TCP가 재전송 대기를 하고 있다’는 쪽이 꽤 유력해집니다.
flowchart TB
accTitle: 재전송 대기를 확정하는 확인 포인트
accDescr: 같은 Seq의 재전송이 나오고 있는지, 재전송까지의 시간 차가 정지 시간과 일치하는지, fast retransmission이 아니라 RTO 만료 대기로 보이는지의 3점이 맞으면, 앱의 정지가 아니라 TCP의 재전송 대기라는 가설이 유력해짐을 나타낸다.
c1["같은 Seq의 재전송이 나오고 있는가"] --> conc["TCP가 재전송 대기를 하고 있다"]
c2["시간 차가 정지 시간과 일치하는가"] --> conc
c3["RTO 만료 대기로 보이는가"] --> conc
conc -.-> not["앱이 멈춰 있는 것이 아니다"]
그림7: 이 3점이 맞물리면, ‘앱 정지’가 아니라 ‘TCP의 재전송 대기’가 꽤 유력해진다.
4.3. 협상된 TCP 옵션을 본다
다음에 본 것이 연결 시작 시의 SYN / SYN-ACK입니다. 타임스탬프는 TCP 연결의 3-way handshake에서 협상되므로, 여기에 TSopt가 나오지 않으면 그 연결에서는 쓰이지 않습니다.
sequenceDiagram
participant Host as 호스트
participant Cam as 카메라 측
Host->>Cam: SYN + TSopt ?
Cam-->>Host: SYN/ACK + TSopt ?
Host->>Cam: ACK
Note over Host,Cam: 여기서 협상되어야 비로소 이후 세그먼트에서 TSopt를 쓸 수 있다
그림8: 타임스탬프는 3-way handshake에서 협상된다. SYN / SYN-ACK에 TSopt가 없으면 그 연결에서는 쓰이지 않는다.
여기를 보지 않고 OS 설정만 만지면, ‘켰을 텐데 효과가 없다’는, 또 한 번 눈에 잘 안 띄는 실수가 됩니다. 설정값보다 wire의 사실이 더 강합니다.
5. RFC1323 타임스탬프가 효과가 있는 이유
실무에서는 ‘RFC1323의 타임스탬프’라는 호칭이 아직 남아 있지만, 현행 정리는 RFC 7323입니다. 이 기사에서는 관용에 맞춰 RFC1323이라고 쓰면서, 의미로는 TCP timestamps option을 가리킵니다.
5.1. 타임스탬프는 RTTM과 PAWS를 위한 것
TCP의 timestamps option은 주로 2가지 목적으로 쓰입니다.
- RTTM(Round-Trip Time Measurement)
- PAWS(Protect Against Wrapped Sequences)
여기서 이번에 효과가 있었던 것은 RTTM 쪽입니다. 송신한 세그먼트의 TSval을 상대가 ACK의 TSecr로 돌려줌으로써, 송신 측은 RTT를 더 세밀하고 더 정확하게 측정하기 쉬워집니다.
flowchart TB
accTitle: timestamps option의 2가지 목적
accDescr: TCP의 timestamps option은 RTTM 즉 왕복 시간의 측정과, PAWS 즉 시퀀스 번호의 한 바퀴 대책의 2가지 목적으로 쓰이며, 이번 사례에서 효과가 있었던 것은 RTTM 쪽임을 나타낸다.
tso["timestamps option"] --> rttm["RTTM(왕복 시간의 측정)"]
tso --> paws["PAWS(시퀀스 번호 한 바퀴 대책)"]
rttm --> hit["이번에 효과가 있었던 것은 이쪽"]
rttm -.-> how["TSval을 ACK의 TSecr로 돌려 측정한다"]
그림9: 타임스탬프의 목적은 RTTM과 PAWS 두 가지. 이 사례에서 효과가 있었던 것은 RTT 측정 쪽.
5.2. 재전송 시 RTT 측정의 모호함을 제거할 수 있다
재전송이 들어가면, 타임스탬프 없이는 ‘이 ACK는 처음 송신에 대한 것인지, 재전송에 대한 것인지’가 모호해집니다. 이것이 이른바 Karn의 알고리즘이 신경 쓰는 점입니다.
RFC 6298에서는, 재전송된 세그먼트에서는 RTT 샘플을 취해서는 안 된다고 되어 있습니다. 이유는, 어느 송신에 대한 ACK인지 모르기 때문입니다. 다만 timestamps option이 있으면 이 모호함을 제거할 수 있습니다. ACK에 들어오는 TSecr을 보면, 어느 TSval을 가진 세그먼트가 도착했는지를 식별할 수 있기 때문입니다.
sequenceDiagram
participant Host as 송신 측
participant Cam as 수신 측
Host->>Cam: Seq=N, TSval=1000
Note over Host,Cam: 이 세그먼트가 로스
Note over Host: ACK가 오지 않아 기다린다
Host->>Cam: Seq=N, TSval=2000 을 재전송
Cam-->>Host: ACK, TSecr=2000
Note over Host: 어느 송신에 대한 응답인지 판별할 수 있다
그림10: TSecr을 보면, 그 ACK가 처음 송신과 재전송 중 어느 쪽에 대한 응답인지 판별할 수 있다.
여기가 이번 개선의 핵심입니다.
5.3. 이 사례에서 대기 시간을 줄일 수 있었던 이유
이 사례에서는 패킷 로스가 가끔 발생하고, 그때마다 RTT / RTO의 추정이 보수적으로 기울기 쉬운 상태였습니다. 타임스탬프를 켜면, 재전송을 포함하는 상황에서도 RTT 추정을 갱신하기 쉬워져, RTO 추정이 오래된 채로 계속 부푸는 시간을 억제할 수 있습니다.
여기는 건너뛰기 쉬운 곳이므로, 조금 더 자세히 나눠 둡니다.
먼저, RTO의 하한 자체는 타임스탬프 유무로 바뀌지 않습니다. RFC 6298은, 계산한 RTO가 1초 미만이면 1초로 올림해야 한다고 합니다. 구현이 독자적인 하한을 갖는 경우도 있고, Windows의 경우는 Get-NetTCPSetting에 나오는 MinRtoMs가 그에 해당합니다(10밀리초 단위로 20~300밀리초 범위를 취합니다). 즉 ‘타임스탬프를 넣었으니 하한이 내려갔다’가 아닙니다.
효과가 있는 것은 그 앞단입니다. RFC 6298은 다음 3가지를 정하고 있습니다.
- 재전송 타이머가 만료될 때마다, RTO를 2배로 한다(지수 백오프)
- 백오프한 RTO는, 새로운 RTT 측정이 얻어졌을 때 원래로 돌아온다
- 그 ‘새로운 RTT 측정’은, 재전송하지 않은 데이터가 보내져 ACK된 때에만 얻을 수 있다
게다가 Karn의 알고리즘에 의해, 재전송한 세그먼트에서는 RTT 샘플을 취해서는 안 됩니다. 다만 이 제약은 timestamps option을 쓰고 있는 경우에는 해제됩니다. 5.2대로, TSecr을 보면 어느 송신에 대한 ACK인지 판별할 수 있기 때문입니다.
여기까지 늘어놓으면 흐름이 보입니다. 로스가 산발적으로 이어지는 환경에서는, 타임스탬프가 없으면 2와 3의 조건이 좀처럼 갖춰지지 않아, 배증된 채인 RTO가 실측에 근거해 되돌아올 때까지의 시간이 길게 남습니다. 그 상태에서 다음 로스가 오면, 1초가 아니라 2초, 4초라는 대기에서 시작해 버립니다. 타임스탬프가 있으면 재전송을 포함하는 구간에서도 다시 잴 수 있으므로, 이 ‘되돌아올 수 없는 시간’이 짧아진다는 것이 이번에 효과가 있었던 흐름입니다.
flowchart TB
accTitle: 배증한 RTO가 되돌아오는 조건과 타임스탬프의 효과
accDescr: 타임아웃마다 RTO는 배증하고, 새로운 RTT 측정이 얻어졌을 때 원래로 돌아오지만, 그 측정은 재전송하지 않은 데이터의 ACK에서만 얻을 수 있으므로, timestamps로 이 제약이 해제되면 배증한 RTO가 되돌아올 수 없는 시간이 짧아짐을 나타낸다.
backoff["타임아웃마다 RTO가 배증"] --> ret["새로운 RTT 측정으로 원래로 돌아온다"]
ret -.-> limit["측정은 미재전송 데이터의 ACK에서만"]
ts2["timestamps로 재전송 구간에서도 잴 수 있다"] --> often["다시 잴 기회가 늘어난다"]
often --> short["배증 RTO가 되돌아올 수 없는 시간이 줄어든다"]
그림11: 하한이 내려가는 것이 아니라, 배증한 RTO가 실측으로 빨리 되돌아오게 되는 것이 효과의 핵심.
솔직히 적어 두면, 이 기사에서는 개선 후의 RTO 실측값까지는 잡지 않았습니다. 알고 있는 것은, 초 단위의 정지가 현장에서 문제가 되지 않을 정도까지 줄었다는 데까지입니다. 효과를 숫자로 보이고 싶은 경우에는, 7장의 표시 필터와 Time delta from previous displayed packet 열을 써서, 재전송까지의 시간 차 분포를 before / after로 집계하는 것이 가장 지름길입니다.
바꿔 말하면, 이번에 한 것은 TCP를 빠르게 하는 마법이 아니라, TCP가 필요 이상으로 오래 눈치를 보는 시간을 줄이는 것입니다.
물론 RFC 7323도 ‘RTT 샘플이 늘면 무엇이든 깨끗이 해결된다’고는 말하지 않습니다. RTO 최적화에 효과가 있는 정도는 한정적인 면도 있습니다. 다만 재전송 시의 모호함을 제거할 수 있다는 점은, 이번과 같은 환경에서 그대로 효과가 있는 경우가 있습니다.
주의점도 있습니다.
- 이것은 TCP stack의 구현에 의존하는 부분이 있습니다
- 타임스탬프만으로 패킷 로스 자체는 사라지지 않습니다
- 물리 계층이나 중간 기기가 나쁘면, 근본 원인은 따로 있습니다
- SACK이나 NIC 드라이버, 오프로드 설정, 스위치 측 문제도 따로 보는 편이 좋습니다
다만, 이번처럼 ‘로스는 0이 아니다’ ‘그래도 정말 아픈 것은 초 단위의 대기’라는 환경에서는, 꽤 효과가 있는 경우가 있습니다.
6. 실제로 한 대책
6.1. 타임스탬프를 켠다
대책으로는, 연결 양쪽에서 timestamps option이 협상될 수 있는 상태로 만들었습니다. Windows 계열에서는 RFC 1323 옵션으로 다뤄지는 경우가 있고, OS 설정이나 네트워크 설정의 영향을 받습니다.
구체적인 절차를 적어 둡니다. 먼저, 지금 어떻게 되어 있는지를 봅니다.
netsh interface tcp show global
출력 안에 RFC 1323 타임스탬프 항목이 있으므로, 거기가 켜져 있는지를 확인합니다. 켜려면 관리자 권한의 명령 프롬프트에서 이렇게 합니다.
netsh interface tcp set global timestamps=enabled
timestamps에 지정할 수 있는 것은 disabled / enabled / default의 3가지이고, default는 시스템 기본값으로 되돌리는 지정입니다.
PowerShell에서 보거나 설정하는 경우는 이쪽입니다.
Get-NetTCPSetting | Select-Object SettingName, Timestamps, MinRtoMs, InitialRtoMs
Set-NetTCPSetting -SettingName InternetCustom -Timestamps Enabled
Timestamps에 지정할 수 있는 것은 Enabled / Disabled입니다. 변경할 수 있는 SettingName은 Windows 버전에 따라 다릅니다. 그래서 바로 Set-를 치지 말고, 먼저 Get-NetTCPSetting으로 실제로 있는 이름을 확인하십시오. 존재하지 않는 이름을 넘기면 거기서 멈춥니다.
오래된 환경에서 레지스트리를 직접 보려면, 다음 키의 Tcp1323Opts(REG_DWORD)입니다.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
값의 의미는, 0이 RFC 1323 옵션 무효, 1이 window scaling만, 2가 timestamps만, 3이 둘 다 유효입니다. 비트 0이 window scaling, 비트 1이 timestamps에 해당한다고 기억하면 헤매지 않습니다.
설정할 때의 주의가 3가지 있습니다.
- 효과가 있는 것은 신규 연결부터입니다. 타임스탬프는 3-way handshake에서 협상되므로, 이미 맺어 둔 연결에는 효과가 없습니다. 장치 측 연결을 다시 맺어야 합니다
- 양쪽이 지원하지 않으면 협상이 되지 않습니다. 호스트 측만 켜도, 카메라 측이 SYN/ACK에서 TSopt를 돌려주지 않으면 그 연결에서는 쓰이지 않습니다
- 설정은 연결의 성격도 바꿉니다. 타임스탬프는 TCP 헤더를 크게 하므로, 한 세그먼트에 실리는 데이터는 조금 줄어듭니다
다만 실무에서는 ‘설정 화면에서 켜져 있다’보다, ‘SYN / SYN-ACK의 실제 패킷에 TSopt가 실려 있다’가 더 중요합니다. 여기는 정말 그렇습니다.
flowchart TB
accTitle: 타임스탬프 설정 시의 주의 3점
accDescr: 타임스탬프 설정은 3-way handshake에서 협상되므로 신규 연결부터만 효과가 있고, 양단이 대응하지 않으면 성립하지 않으며, 헤더가 커져 한 세그먼트에 실리는 데이터가 조금 줄어든다는 3가지 주의점을 나타낸다.
care["설정 시의 주의 3점"] --> n1["효과가 있는 것은 신규 연결부터"]
care --> n2["양쪽의 지원이 필요"]
care --> n3["헤더가 늘어나고 데이터는 조금 줄어든다"]
n1 -.-> re["장치 측 연결을 다시 맺는다"]
그림12: 설정만으로는 끝나지 않는다. 연결의 재수립과 상대 측 대응의 확인이 필요하다.
6.2. SYN / SYN-ACK에서 TSopt를 확인한다
켠 뒤에는 3점을 확인했습니다.
- 문제의 연결의 SYN에 TSopt가 있는가
- SYN/ACK 측도 TSopt를 돌려주고 있는가
- 이후 데이터 세그먼트와 ACK에도 TSopt가 계속해서 실려 있는가
여기가 확인되어야 비로소, ‘그 연결에서 timestamps가 실제로 쓰이고 있다’고 말할 수 있습니다.
6.3. 그래도 효과가 없을 때 볼 곳
타임스탬프를 켜도, 이런 경우에는 개선이 둔한 경우가 있습니다.
- 로스율 자체가 높다
- 중간 기기가 TCP option을 깨뜨리거나, 드롭하거나, 변형한다
- NIC / 드라이버 / 오프로드 주변에 다른 문제가 있다
- 앱이 하나의 동기 호출에 전체를 매달아 두어, 한 번의 대기가 그대로 전체 정지로 보인다
- 실제로는 TCP가 아니라, 카메라 측의 처리 정지나 장치 안 큐 막힘이 주원인
그래서 대책은 이 순서로 진행하는 편이 알기 쉽습니다.
- 먼저 wire에서 재전송 대기를 확인한다
- TSopt의 협상 유무를 본다
- timestamps를 켜고 개선 차이를 본다
- 아직 남으면, 로스 원인과 앱 설계를 따로 파고든다
flowchart TB
accTitle: 대책을 진행하는 순서
accDescr: 먼저 wire에서 재전송 대기를 확인하고, TSopt의 협상 유무를 보고, timestamps를 켜 개선 차이를 보고, 그래도 남으면 로스 원인과 앱 설계를 따로 파고드는 대책 순서를 나타낸다.
s1["wire에서 재전송 대기를 확인"] --> s2["TSopt의 협상 유무를 본다"]
s2 --> s3["timestamps를 켜고 차이를 본다"]
s3 --> s4["남으면 로스 원인과 설계를 따로 파고든다"]
그림13: 확인→협상→켜기→나머지 조사 순으로 진행하면, 효과가 없는 원인을 분리하기 쉽다.
7. Wireshark에서 볼 포인트
원인 분리에 쓰기 쉬운 표시 필터를 적어 둡니다.
tcp.stream eq <대상 스트림>
tcp.analysis.retransmission
tcp.analysis.fast_retransmission
tcp.analysis.lost_segment
tcp.options.timestamp.tsval
tcp.options.timestamp.tsecr
보는 방법에는 몇 가지 요령이 있습니다.
tcp.stream으로 대상 연결만 좁힌다Time delta from previous displayed packet을 내어, 멈춰 있는 초를 그대로 본다- 문제의 순간에
Retransmission이 나오고 있는지 확인한다 - 연결 시작 시의 SYN / SYN-ACK에서 TSopt가 협상되어 있는지 확인한다
- ACK의
TSecr이 돌아오고 있는지를 본다
화면이 어떻게 보이는지도 글로 적어 둡니다. 이 패턴은 익숙해지면 한눈에 알 수 있습니다.
| 볼 곳 | 어떻게 보이는가 |
|---|---|
| 패킷 목록의 Info 열 | 재전송 패킷에는 [TCP Retransmission]이 붙습니다 |
| 행의 색 | Wireshark의 기본 색 구분 규칙 ‘Bad TCP’에 해당하므로, 그 행만 검은 배경에 빨간 글자가 됩니다. 훑어봐도 잡을 수 있습니다 |
| 상세 창 | 해당 행을 골라 Transmission Control Protocol을 펼치고, 그 안의 SEQ/ACK analysis를 열면 재전송으로 판정되었다는 내용이 나옵니다 |
| 시간 차 | Time delta from previous displayed packet을 열로 내면, 그 행이 직전 표시 패킷에서 몇 초 비었는지를 읽을 수 있습니다. 여기가 1초, 2초로 늘어섭니다 |
| SYN의 Options | SYN 행을 골라 Options를 펼치고, Timestamps 항목이 있는지로 TSopt 유무를 알 수 있습니다 |
전형적인 순서는 이렇습니다. 먼저 같은 Seq의 행이 1초 뒤에, 다시 그 2초 뒤에 한 번 더 나오고, 마지막 행 직후에 ACK가 돌아와, 거기서부터 통상적인 주고받기가 재개됩니다. 이 ‘공백의 수 초’와 앱 측 로그에서 응답이 멈춰 있던 시간이 일치하면, 범인은 거의 확정입니다.
로그와 패킷을 맞춰 볼 때는, 앱 시각과 캡처 시각의 기준 차에도 주의가 필요합니다. 여기가 어긋나면 다른 건을 범인 취급하기 쉽습니다.
flowchart TB
accTitle: Wireshark로 범인을 확정하는 흐름
accDescr: tcp.stream으로 대상 연결만 좁히고, 시간 차 열로 멈춰 있는 초를 직접 보며, 그 공백의 수 초가 앱 로그에서 응답이 멈춰 있던 시간과 일치하면 범인은 거의 확정이라는 흐름을 나타낸다.
filt["tcp.stream으로 대상 연결에 좁힌다"] --> delta["시간 차 열로 공백의 초를 본다"]
delta --> re["같은 Seq의 재전송이 늘어선 것을 확인"]
re --> match{"앱의 정지 시간과 일치?"}
match -->|"예"| fix["범인은 거의 확정"]
match -->|"아니오"| other["시각의 기준 차나 다른 요인을 의심한다"]
그림14: 좁힌다, 시간 차를 본다, 맞춰 본다. 이 세 가지로 ‘공백의 수 초’의 정체를 확정한다.
8. 대략적인 구분
| 증상 | 먼저 의심할 것 | 처음에 할 일 |
|---|---|---|
| 수 초 단위로 가끔 멈춘다 | TCP의 RTO 대기 | 재전송과 시간 차를 패킷으로 확인 |
| 매번 거의 같은 타이밍에 멈춘다 | 앱 안 대기, 장치 측 처리, 고정 타임아웃 | 스레드, SDK 호출, 장치 로그를 본다 |
| 고부하 때만 악화한다 | CPU, GC, 큐 막힘 | CPU, 인터럽트, 메모리, 큐 길이를 본다 |
| 여러 연결이 한꺼번에 나빠진다 | 물리 계층, 스위치, 중간 기기 | NIC, 케이블, 포트 통계, 중간 기기 로그를 본다 |
| 설정을 바꿨는데 변하지 않는다 | TCP option이 협상되지 않았다 | SYN / SYN-ACK를 다시 확인한다 |
마지막 행은 정말 많습니다. 설정을 만진 만족감과, wire상에서 쓰이고 있는 사실은 별개입니다.
9. 정리
이번의 포인트:
- ‘가끔 수 초 멈춘다’는 앱 정지가 아니라 TCP의 재전송 대기인 경우가 있다
- 정지 시간이 RTO의 대기 방식과 맞고,
Retransmission이 보이면 원인 가설로 꽤 타당하다 - TCP timestamps option은 RTTM과 PAWS의 메커니즘으로, 재전송 시 RTT 측정의 모호함을 제거할 수 있다
- 이 사례에서는 RFC1323 계열 타임스탬프를 켜서, RTO가 과도하게 보수적인 채로 남는 시간을 억제할 수 있었다
피하고 싶은 진행 방식:
- 앱 로그만으로 통신 정지의 범인을 정한다
- OS 설정만 보고, 실제 패킷을 보지 않는다
- 타임스탬프를 켜면 로스 원인까지 사라진다고 생각한다
실무에서 효과가 있는 진행 방식:
- 먼저 wire를 본다
- 재전송과 대기 시간의 형태를 확인한다
- TSopt의 협상을 확인한다
- 개선 후에도, 로스 원인과 앱 설계는 따로 파고든다
즉, 이런 문제는 ‘빠르게 하는’ 것보다 ‘어디서 기다리고 있는지를 맞추는’ 편이 먼저입니다. 거기만 빗나가지 않아도 조사는 꽤 짧아집니다.
10. 참고 자료
- RFC 1323 - TCP Extensions for High Performance
- RFC 7323 - TCP Extensions for High Performance
- RFC 5681 - TCP Congestion Control
- RFC 6298 - Computing TCP’s Retransmission Timer
- Description of Windows TCP features - Windows Server | Microsoft Learn
- Netsh commands for Interface Transmission Control Protocol - Microsoft Learn
- Set-NetTCPSetting - Microsoft Learn
- Get-NetTCPSetting - Microsoft Learn
- Wireshark User’s Guide - Time Display Formats And Time References
- Wireshark User’s Guide - Packet Colorization
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
네트워크 드라이브와 UNC 경로의 함정 ── 업무 앱에서 파일 서버(공유 폴더)를 다루는 실무
업무 앱에서 공유 폴더로 출력·감시할 때 자주 겪는 문제를 정리합니다. 드라이브 문자(Z:)가 서비스에서 보이지 않는 이유, 실행 계정별로 필요한 권한, 오류 1219, FileSystemWatcher 주의점까지 설명합니다.
Application Verifier로 만드는 Windows 이상 경로 테스트 기반
Application Verifier가 무엇인지, Handles, Heaps, Low Resource Simulation, !htrace를 사용한 Windows 이상 경로 테스트 기반 구축과 함께 정리합니다.
산업용 카메라 장기 가동 크래시 조사 - 핸들 누수편
Windows 앱이 장시간 가동 뒤에 갑자기 크래시할 때의 보는 법을, 산업용 카메라 제어 앱 사례로 핸들 누수를 찾는 방법과 로그 설계 관점에서 정리합니다.
절전에서 재개하면 깨지는 앱 ── 전원 이벤트의 구조와 재개에 강한 업무 앱을 만드는 방법
노트북을 열었더니 업무 앱의 통신이 끊어져 있었다――원인은 절전을 전제하지 않은 설계입니다. WM_POWERBROADCAST에 의한 알림의 흐름, Modern Standby의 동작, 끊김·재연결 설계, 절전 억제와 조사 명령까지를 1차 정보로 설...
「응답 없음」의 정체 ── Windows가 앱을 「멈췄다」고 판단하는 구조와, 멈추지 않는 설계
Windows의 「응답 없음」은 창이 5초 동안 메시지를 꺼내지 않으면 OS가 판단해 고스트 창으로 교체하는 구조입니다. 판단의 내부 동작부터 멈추는 전형적인 원인, UI 스레드에서 무거운 처리를 빼내는 설계, hang 조사 절차까지 설명합니다.
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
장애 조사 & 장기 가동 장애
간헐적 장애, 통신 진단, 장기 가동 크래시, 실패 경로 테스트 기반을 정리한 토픽 페이지입니다.
관련 사례
실제 정리와 개선 진행 방식이 가까운 사례 페이지입니다.
수 초 단위의 통신 정지를 분리한 사례
드물게 발생하는 통신 정지를 재전송 대기와 OS 측 조건으로 나누어 분리한 사례 페이지입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
장애 조사 & 원인 분석
재현하기 어려운 통신 정지를 패킷과 증거로 원인을 분리하는 이야기이므로, 장애 조사·원인 분석에 바로 연결되는 주제입니다.
Windows 앱 개발
장치 연동을 포함한 Windows 앱으로서, 통신 설계나 감시를 구현 쪽에서 다시 보는 상담으로도 이어집니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- TCP Retransmission(TCP 재전송)이란 무엇인가요?
- 송신한 패킷에 대한 ACK(확인 응답)가 돌아오지 않을 때, TCP가 같은 데이터를 다시 보내는 메커니즘입니다. 중간 어딘가에서 패킷이 손실되면, 송신 측은 ACK를 기다리다가 오지 않으면 재전송 타이머(RTO) 만료를 기다린 뒤 재전송합니다. 앱에서 보면 '수 초 멈춘' 것처럼 보이지만, TCP 입장에서는 '아직 ACK가 오지 않아 재전송 타이머 만료를 기다리고 있었을' 뿐인 정지 방식은 흔합니다. 패킷 캡처에서는 TCP Retransmission으로 관측할 수 있습니다.
- TCP Retransmission이 발생하는 원인은 무엇인가요?
- 직접적인 트리거는 패킷 로스이며, ACK가 돌아오지 않아 재전송이 일어납니다. 로스의 발생원으로는 물리 계층(케이블이나 포트), NIC나 그 드라이버·오프로드 설정, 스위치나 중간 기기의 문제 등을 개별적으로 봐야 합니다. TCP timestamps를 켜는 등으로 재전송 후의 대기 시간을 줄일 수는 있지만, 로스 자체를 없애는 마법은 아니므로 로스 원인의 조사는 따로 필요합니다. 중간 기기가 TCP 옵션을 깨뜨리거나 드롭하는 경우, 실은 TCP가 아니라 장치 측의 처리 정지가 주원인인 경우도 있습니다.
- TCP 재전송으로 통신이 수 초나 멈추는 이유는 무엇인가요?
- TCP의 재전송 타이머(RTO)가 보수적으로 기다리기 때문입니다. RFC 6298에서는 초기 RTO는 1초가 기준이며, 계산 결과가 그보다 작아도 1초로 올림하고, 타임아웃이 일어날 때마다 배증합니다. 그래서 조건이 나쁘면 1초, 2초, 4초처럼 기다리게 됩니다. 작은 request/response 중심의 제어 통신에서는 duplicate ACK를 충분히 모아 fast retransmit에 올라타기보다 먼저 RTO 대기가 표면에 나오기 쉬워, 드문 수 초 정지로 나타납니다. TCP timestamps option을 켜면 재전송 시 RTT 측정의 모호함을 제거해 RTO 추정이 과도하게 보수적인 채로 남는 시간을 줄일 수 있는 경우가 있습니다.
- Wireshark에서 TCP Retransmission을 조사하려면 어떻게 하나요?
- 표시 필터로 tcp.analysis.retransmission, tcp.analysis.fast_retransmission, tcp.analysis.lost_segment 등을 쓸 수 있습니다. tcp.stream으로 대상 연결만 좁히고, Time delta from previous displayed packet을 표시해 멈춰 있는 초를 직접 확인하며, 문제의 순간에 Retransmission이 나오는지, 재전송까지의 시간 차가 정지 시간과 일치하는지를 봅니다. TCP timestamps를 쓰고 있는지는 연결 시작 시의 SYN / SYN-ACK에서 TSopt가 협상되었는지로 확인합니다. 설정 화면에서 켜져 있는 것보다, 실제 패킷에 TSopt가 실려 있는 사실이 더 중요합니다.