TCP 특성
- Point to point: 일대일 통신
- Reliable, in-order byte stream: 신뢰성 있는, 순서대로 전송되는 바이트 스트림
- Full duplex data: 전이중 데이터 통신
- Cumulative ACKs(Ack(10)은 0부터 9까지 잘 받았고, 다음으로 10을 기대하는 의미)
- Pipelining: 윈도우를 사용하여 효율적인 데이터 전송
- Connection-oriented: 연결 지향적
- Flow control: 흐름 제어
- Congestion Control: 혼잡 제어
- TCP segment structure: 소스 포트, 목적지 포트, 시퀀스 번호, ACK 번호, 수신 윈도우, 체크섬, 플래그들, 옵션 등으로 구성
TCP segment structure
src port#, dest port#, seq#(데이터보낼 때 시퀀스넘버), ack#(몇번까지 잘받았고, 이제 #번 내놔), receive window, checksum, 여러개의 플래그들, options..
TCP헤더는 옵션을 제외하고 20byte이다.
Ack 세그먼트는 기본적으로 20byte이다.(하지만 때로는 데이터와 함께 보내는 Ack도 있어 20바이트가 넘을 수도 있음)
TCP sequence numbers, ACKs
TCP는 application레이어로부터 받은 메시지를 byte단위로 번호를 붙인다.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
(예를들어 10바이트짜리 메시지인 경우)
이것을 transport layer에서 작은 크기의 세그먼트들로 나눌 수 있다.
예를들어 2바이트, 4바이트, 2바이트, 2바이트로 나누었다고 치자. 그럼 아래와 같이 될것이다.
헤더+(0,1) /헤더+(2,3,4,5) / 헤더+(6,7) / 헤더+(8,9)
그럼 총 4개의 세그먼트가 생기는데,
각각의 세그먼트에서 맨 앞에있는 바이트번호가 세그먼트의 시퀀스넘버가 된다.
(참고: 실제 구현에서 initial seq#은 0부터 시작하지 않고 랜덤하게 정해진다)
ACK
TCP의 ACK(n)은 n-1바이트까지 잘 받았으니, n번 바이트를 달라는 의미로 해석하면 쉽다.
또한, ACK을 Data와 함께 보낼 수 있다. 이를 piggy backing이라고 함. data와 ack을 따로 보내는 것보다 효율적이다.(헤더가 한번만 쓰이니까)
TCP의 타이머는 윈도우에 하나만 존재한다. 하지만 타임아웃시 재전송은 윈도우의 모든 패킷을 재전송하는것이 아니라, 필요한 패킷만 재전송한다.
Ack이 중간에 로스가 나더라도, cumulative ack이므로 다음 ack을 통해, 잘 전달받았다는 것을 알 수 있다.
그런데, 그럼 ack이 항상 필요한게 아니니까 좀 덜보내도 되지않나?-> delayed ack 기법도 있음.데이터를 받고 일정시간동안 기다리고, 만약 기다리는동안 다음 데이터가 오면 다음데이터에 대한 액만 보냄
TCP Fast Retransmit
예를들어, 5번 데이터를 전송한 상황을 보자.
그 중 2번째 데이터가 로스가 난 경우를 생각해보면, receiver는 1번 데이터를 받고 ACK(2)를 보내고, 3,4,5번을 받고 ACK(2)를 또 보낼것이다.
그럼 sender는 중복된 ACK(2)를 세번(총 네번)받게된다. 그럼, sender는 타이머 타임아웃이 되지 않아도 3번의 중복된 ACK을 통해 패킷로스를 감지하여 해당 패킷을 즉시 재전송한다.
3-way Handshake
TCP는 통신을 시작하기 위해서 필요한 정보를 초기에 교환해야한다.
1. initial seq #: 시퀀스넘버 초기값을 알아야 처음 보낸 데이터가 inorder인지, 혹은 앞에 또다른 데이터가 로스난것인지 판단할 수 있다. 또, TCP는 양방향통신이므로 두 호스트가 서로 자신의 initial seq#을 보내줘야 한다.
2. receiver buffer size: 버퍼용량이 얼마나 남았는지 보내줘야 한다.(추후 설명할 flow control)
1. 처음 sender가 핸드쉐이크를 시작할 때, SYNbit=1로 설정하고, 자신의 initial seq#를 기입하여 보낸다.
2. receiver도 SYNbit=1로 설정하고, 자신의 initial seq#를 기입하고, ACKbit=1(ACK이란 의미), ACKnum=sender의 initial seq#+1
3. 다시 sender는 ACKbit=1, ACKnum=receiver initial seq#+1 설정하여 보낸다. 데이터도 함께 보낼 수 있다
TCP는 접속을 종료할 때도 일련의 과정이 필요하다
1. Finbit=1로 패킷을 보낸다.
2. 서버는 ACK을 보냄
3. 잠시 기다린다.
4. 서버가 FINbit=1로 패킷 보냄
5. 클라이언트가 ACK을 보냄
6. 잠시 기다린다.
7. 완전히 연결종료
잠시 기다리는것은, 상대가 이전에 보낸 메세지가 늦게 도착할 수도 있으므로 약간의 시간을 가지는 것이다.
TCP timer timeout, RTT, EWMA
TCP 타이머 타임아웃시간은 어떻게 정하는 것이 좋을까?
RTT보다 살짝 크게 정하면 될 것 같다.
하지만, RTT는 매번 변하게된다(큐잉 딜레이 등으로 인해) 따라서 RTT정도로 맞추는것이 힘들다.
따라서 RTT를 예측하는 방식을 사용한다.
Exponential weighted moving average ( EWMA)
새로운 EstimatedRTT = (1-a)*지난 EstimatedRTT + a*현재 SampleRTT
알파값이 1에 가까울수록 실제 값에 영향을 많이 받는다. 또한, 옛날 정보보다 현재에 가까울수록 영향력이 크다.
이렇게 얻은 ERTT에, margin값으로 4*표준편차를 더해 타이머로 사용한다.
(표준편차를 구할 때도 estimation방식으로 구한다)
TCP Flow Control
데이터가 수신되면
transport 레이어는 세그먼트를 receiver buffer에 넣는다.
그럼, 어플리케이션 레이어에서 버퍼를 통해 데이터를 가져간다.
따라서 sender는 dest의 receiver buffer 의 free buffer space을 보고 적절하게 데이터를 보내야한다.
이를 위해 receiver는 ack을 보낼 때 헤더의 receive window필드를 통해 남은 버퍼 공간 크기를 보내주어야 한다(byte단위).
(또는 데이터패킷에도 receive window정보를 보낼 수 있다)
sender는 dest의 receive window정보를 보고 보낼 수 있는 만큼만 데이터를 전송한다.
만약 receiver가 보낸 ack에서 rwnd가 0B인 경우, 버퍼공간이 없으므로 더이상 데이터를 보내면 안된다.
그럼, 언제 다시 데이터 전송을 재개해야할까?
방법 1. receiver가 데이터를 보낼 일이 있을 때(TCP는 양방향이므로 receiver였던 애가 데이터를 보낼 수 있다.)
rwnd값을 갱신하여 보낸다.
방법2. 주기적으로 sender가 receiver에게 1B짜리 probe패킷을 보낸다. (의미없는 dummy data) 그럼, receiver가 ack을 보내는 것을 보고 rwnd를 확인할 수 있다.
TCP retransmission
타이머 타임아웃시 윈도우에서 가장 seq#이 낮은 패킷만 재전송한다.
정리하자면, TCP에서 재전송하는 조건
1. 타임아웃시
2. 세개의 중복 ACK 수신시(Fast retransmission)
두가지가 있는것이다.
'2023-1 > 컴퓨터네트워크및실습' 카테고리의 다른 글
HTTP (0) | 2023.06.13 |
---|---|
TCP congestion control (0) | 2023.06.12 |
Go-Back-N, Selective Repeat (0) | 2023.06.11 |
Reliable Data Transfer(RDT) (0) | 2023.06.11 |
UDP Server & Client (0) | 2023.06.11 |
댓글