TCP Services
- TCP 는 transport layer 내의 protocol 이다.
Stream Delivery
- application layer 에서 transport layer 로 data 가 전송 될 때, TCP 는 stream delivery 를 사용한다.
- application layer 에서 오는 data 는 packet 이라고 불리는 boundary 가 설정되어 온다. TCP 는 이 boundary 를 지키지 않고 직접 byte 단위로 boxing 해 사용한다. 이를 segment 라고 한다.
- 데이터 전송 시 데이터가 거쳐 가는 buffer 가 있다. TCP 는 buffer 에 데이터를 byte 단위로 채우는 것이다.
- 보내는 쪽의 buffer 은 sending buffer, 받는 쪽은 recieving buffer 라고 한다.
- sending buffer 은 비어있는 empty, 아직 전송이 되지 않은 not sent, 전송이 완료됐지만, 완료 여부를 확인하기 전까지 데이터를 임시로 저장하는 sent 영역으로 나뉜다.
- revieving buffer 은 비어있는 empty 와 아직 application 으로부터 소모되지 않은 데이터가 저장되는 not read 영역으로 나뉜다.
TCP Features
- TCP 의 데이터 packet 은 구별을 위해 byte 당 sequence number 이라는 번호를 부여받는다.
- numbering 의 시작 번호는 임의의 수고, packet size 만큼 증가한다.
- reciever 가 packet 을 받으면, 잘 받았다는 신호로 acknowledgement field (ACK) 를 보낸다.
- ACK 의 설정 방식은 두 가지가 있다.
- Selective ACK : 받은 packet 의 첫 sequence number 표기
- Cumulative ACK : 다음으로 받고자 하는 packet 의 첫 sequence number 표기
- TCP 는 cumulative 방식을 사용한다.
Segment
- TCP 의 segment 는 header 와 data 로 구성된다. header 에는 데이터 전송의 여러 정보가 담긴다.
- header 의 기본 요소는 32bit (4 byte) 로 이루어진 5개의 줄이다. 즉, 기본 길이는 20 byte 이다. 여기에 추가 요소가 붙으면 60 byte 까지 늘어날 수 있다.
1. Source / Destination port address
process to process communication 을 위한 port 주소
2. Sequence Number
3. Acknowledgement number
4. HLEN (header length)
header 의 길이를 표시한다. 길이는 20 ~ 60 byte 인데, 이를 4 bit 에 표현하기 위해 실제 길이를 4로 나누어 저장한다. 최댓값이 15가 되기 때문에, 1111로 저장할 수 있는 것이다. 이를 위해 options and padding 의 길이를 4의 배수로 맞추기도 한다.
5. Reserved
만일을 위해 비워두는 자리다.
6. Control Field
여러 상황을 표시하기 위해 6개의 flag bit 을 저장한다. 예를 들어 ACK field 가 1로 set 되어 있다면, 해당 packet 은 ACK 을 보내는 packet 이니 ACK 을 확인하라는 의미를 내포한다.
7. Window Size
추후 서술할 flow control 을 위한 수치다. sending / recieving buffer 의 공간을 표기한다.
8.Checksum
데이터 전송 이후 error check 를 위한 수치다.
9. Urgent Pointer
다루지 않는 영역이다.
Checksum Calculation
- 데이터 전송 시 bit failure 등의 오류를 찾기 위한 검산법이다.
- header 의 값을 16 bit 씩 끊어서 줄세운다.
- 줄세운 값을 모두 더하고, 보수 값을 취한 값이 checksum 이다.
- 이렇게 구한 값을 받은 packet 에 저장된 checksum 값과 비교해 오류 여부를 찾는다.
- 오류 여부는 찾을 수 없지만, 정확히 어떤 bit 에서 일어났는지는 알 수 없다.
- TCP 에서의 checksum 검산 과정은 필수적이다.
TCP Connection
Connection Establishment
- TCP 는 connection oriented 로, server / client 간의 연결이 필요하다.
- server 실행 후 대기 => client 의 연결 요청 => server 의 응답 이 일반적인 과정이다.
- 다음 그림은 위에 설명한 일반적인 과정을 나타낸 그림이다.
- server 가 실행되고, client 의 요청을 받을 준비를 한다.
- client 는 연결 요청 패킷인 SYN 을 전송한다. SYN 패킷을 보면, sequence number (임의의 수인 8000으로 설정) 가 적혀있고, SYN field 가 set 되어있는 것을 알 수 있다.
- SYN 을 받은 client 는 응답 패킷 SYN + ACK 을 보낸다. ACK 이 추가된 이유는 SYN 을 받았다는 사실과 다음으로 받을 데이터를 알리기 위함이다. ACK field 도 set 됨을 알 수 있다.
- client 가 연결 요청을 확인했다는 ACK 을 보내며 연결을 완료한다. ACK 굳이 ACK 으로 답장을 할 필요가 없고, sequence number 도 굳이 표기할 필요가 없다.
- 이러한 양상을 3 way handshake 라고 한다.
Data Transfer
- 연결 과정 이후 데이터 전송을 나타낸 그림이다.
- ack 을 다음으로 받을 데이터의 syn 으로 설정하는 cumulative ack 을 사용함을 알 수 있다.
Connection Termination
- 연결 종료 과정은 연결 과정과 유사하다. 다만, SYN 대신 연결 종료 요청 packet 인 FIN 을 보낸다.
- FIN 의 FIN field 가 set 되어 있음을 확인할 수 있다.
- FIN packet 역시 sequence number 를 하나 소비한다.
- connection 이 terminate 되면 이용하던 buffer 가 지워진다.
- server 의 처리 방법에 따라 ack 과 fin 이 따로 가는 4 way handshake 가 될 수도 있다.
- 두 전송 과정의 시간차가 작으면 3, 크면 4 way 가 된다.
Half Close
- server 와 client 중 한 쪽만 종료되는 상황이다.
- 위 그림은 client 가 먼저 종료되고, server 는 전송할 데이터가 남아 나중에 종료되는 상황이다.
- client 가 먼저 FIN 을 보내고 종료된다. 이때 sending buffer 이 지워진다.
- server 는 FIN 에 대한 ACK 전송 후, 남은 데이터 전송을 진행한다.
- 데이터 전송 완료 후 server 가 FIN 을 보내고, client 는 ACK 을 보낸다. 이때, sending buffer 이 지워졌기에 이외의 데이터는 전송할 수 없다.
- recieving buffer 이 지워지며 연결이 완전히 종료된다.
State Transition Diagram
- 데이터 전송 과정에서 단계에 따라 server 와 client 는 여러가지 state 에 놓인다.
- client 의 state 들을 살펴보자
- SYN-SENT : SYN 을 보내 연결 요청이 간 상황이다.
- ESTABLISHED : SYN + ACK 을 받고 ACK 을 보내 연결이 완료된 상황이다.
- FIN-WAIT 1 : FIN 을 보내 종료 요청이 간 상황이다.
- FIN-WAIT 2 : server 에게 ACK 을 받고 FIN 을 받기 까지의 상황이다. 3 way 에선 생략된다.
- TIME-WAIT : client 가 보낸 FIN 에 대한 ACK 을 보낸 상태이다. 바로 연결이 종료되지 않고
TIME-WAIT 상태에 있는 이유는 추후 서술한다.
- LISTEN : server 가 실행되고 SYN 을 받을 준비를 하고 있는 상태
- SYN-RCVD : SYN 을 받고 SYN + ACK 을 보낸 상태
- ESTABLISHED : ACK 을 받아 연결이 완료된 상태
- CLOSE-WAIT : client 의 종료 요청을 받고, server 가 종료되기 전의 상태
- LAST-ACK : FIN 을 보내 종료 요청을 하고 ACK 을 기다리는 상태
- 위 과정에서 state 간의 전이 과정을 state transition diagram 으로 나타낼 수 있다.
Denying a Connection
- SYN 을 받고 SYN + ACK 을 보내면 연결을 허용하는데, 연결을 거절하는 방법도 있다.
- ACK 대신 RST 를 보내는 것이다.
- RST + ACK 을 보내면 FIN 없이 연결을 강제 종료할 수도 있다.
Iterative Echo Server
- iterative 는 server 가 한 번에 하나의 client 를 상대함을 의미한다.
- echo server 는 받은 data 를 그대로 다시 전송한다.
- 5개의 client 를 한 개의 server 가 순차적으로 상대하는 경우다.
- accpet() 는 최초의 SYN 을 받아주는 server socket 을 인자로 받고, 이후의 read / write 를 담당하는 socket 을 반환한다.
- read() 는 accpet 이 반환한 socket 이 읽은 byte 수를 반환한다. 이는 block 함수로, buffer 가 비어 있으면 lock 이 걸린다. FIN 을 받는 경우에는 0을 반환한다.
- write 는 보낼 메세지와 몇 byte 를 보낼지를 인자로 받는다.
- while 문을 살펴보면, FIN 이 올 때까지 받은 메시지를 그대로 write 한다는 것을 알 수 있다.
Concurrent Server
- iterative server 와 달리, 한 server 가 동시에 여러 개의 client 를 상대하는 경우다.
- server socket 이 여러 개의 socket 을 생성하고, 요청이 오는 client 의 IP, port 주소를 보고 각각 다른 socket 에 할당해 주는 방법이다.
TIME-WAIT
- 앞서 언급했듯이 TIME-WAIT 은 client 가 ACK 을 보낸 후, 바로 종료하지 않고 2MSL (max segment lifetime, 30초에서 1분 사이) 동안 기다리고 종료 되는 것을 말한다.
- TIME-WAIT 의 의미는 두 가지가 있다.
- client 는 연결 종료 후 할당 받았던 port 주소를 반납한다. 이후 새로운 연결을 시도할 때, 새로운 port 주소를 할당 받는데, 이전에 썼던 주소를 그대로 받는 경우가 있다.
이 때, 이전의 연결에서 미처 전송되지 못한 packet 이 있을 수 있다. 이 packet 을 받는 reciever 는 sender 의 주소를 보고 받기 때문에, 오류인지 인식하지 못한다.
그러므로, 2 MSL 동안의 시간동안 client 를 종료시키지 않고 전송되지 못한 packet 들의 소멸을 기다리고 할당됐던 port 주소를 붙잡고 있으면서 위 상황을 방지한다.
- ACK 에 대한 ACK 은 없기 때문에, 연결 종료 과정에서 ACK 도착 전에 연결이 종료되는 경우가 있다. 이 때, FIN + ACK 이 잘 도착하지 않은 것인지, ACK 이 유실된 것인지 판단할 수 없다. 이를 확인하기 위해 FIN 을 다시 보내는데, 이 신호를 받기 위해 TIME-WAIT 동안 대기한다.
Windows in TCP
- packet 을 한 개씩 보내며, ACK 이 올 때까지 대기하는 방법을 stop & wait 이라고 한다. 데이터 전송 전 무조건 확인 과정을 거치기 때문에 확실하고 간단한 방법이지만, 매우 비효율적이다.
- TCP 는 효율성을 추구하기 위해 일정 기준을 정해두고, 그 기준 내에서 여러 개의 packet 을 한 번에 보내는 방법을 택한다. 이 기준이 되는 것을 window 라고 한다.
- 위 그림은 sender 의 window 를 보여주고, ACK 201 이 도착한 상황이다.
- 200 까지는 전송이 완료되어 acknowledged 된 byte 들이다.
- 201 부터 260 까지는 전송이 되었지만, 아직 ACK 이 도착하지 않은 outstanding byte 들이다.
- 261 부터 300 까지는 아직 보내지 않았고, reciever 이 더 받을 수 있는 범위다.
=> acknowledged bytes 와 전송 가능한 byte 를 합쳐 send window size 를 설정한다. 이들의 위치는 두 개의 포인터 변수로 관리된다.
- window size 이후의 byte 들은 아직 전송이 불가하다.
- 위 그림은 reciever 의 window 를 보여준다. recieving buffer 를 펼쳐 놓은 것으로 생각하면 쉽다.
- 201 부터 260 까지는 buffer 에 들어와, app 으로부터 소비되길 기다리는 데이터다.
- 261 부터 300 까지는 recieving buffer 의 빈 공간으로, recieve window size 로 정의된다.
Flow Control
- app 에서 데이터를 얼마나 빨리 소비하냐에 따라 데이터 전송 속도를 조절하는 것을 말한다.
- sender 는 recieving window size (rwnd) 의 정보를 받아, 그에 맞게 데이터를 전송한다.
- rwnd 는 reciever 가 ACK 을 보낼 때, TCP header 에 포함시킨다.
- rwnd 의 값은 원래의 rwnd 값에서 받은 byte 수를 빼고, 소비한 byte 수를 더해 산출된다.
Silly Window Syndrome
1. 송신 측에서의 문제
- flow control 에서, 데이터의 크기가 header 에 비해 너무 작아 생기는 문제다.
- header 의 크기는 IP header 20, TCP header 20 의 기본 40 byte 다. 이에 비해 데이터의 크기가 너무 작으면 비효율적인 전송이 된다.
- 이에 대한 해결책은 데이터를 모아 한 번에 보내는 Nagel algorithm 이다.
- Nagle algorithm 에서 모인 데이터를 보내는 경우는 두 가지가 있다.
- 보낼 데이터가 MSS (max segment size, packet 하나를 꽉 채울 크기) 만큼 쌓이면 전송한다.
- 이전 전송의 ACK 이 도달하는 시간을 max wait time 으로 설정하고, MSS 만큼 데이터가 쌓이지 않았더라도 ACK 이 도착하면 데이터를 전송한다.
- 프로그램의 특징에 따라 on, off 해 사용할 수 있다.
2. 수신 측에서의 문제
- window size 에 비해 데이터 소모량이 너무 작아 발생하는 문제다. 데이터를 조금씩 자주 보내, overhead 가 증가하는 것이 이유다.
- 이에 대한 해결책은 Clark's solution 과 확인응답 지연이 있다.
- Clark's solution
- 빈 공간이 많이 생길 때까지 대기하는 방식이다.
- recieving buffer 에 MSS 또는 buffer 의 절반 크기 만큼의 공간이 생길 때까지 ACK 에 rwnd 0 을 전송해 sender 를 대기 시킨다.
- ACK 이 도착할 때까지 wait 을 시킬 수 없는 delay 가 발생한다.
- 확인응답 지연
- Clark's 와 유사한 방법으로, 일정 공간이 빌 때까지 ACK 자체를 보내지 않는 방법이다.
- sender 는 window size 만큼 데이터를 보낸 후 대기한다.
=> 두 방법에는 sender 가 stop 되는 시점이 다르다는 차이가 있다.
SYN Flooding
- client 가 연결 요청을 보낼 때, server socket 에 SYN 을 보내고 server 는 SYN+ACK 을 다시 보낸다. 이 과정이 완료되면 연결 요청을 보낸 client 들은 연결 요청 대기 큐에 push 된다.
- 연결 요청 대기 큐에 있는 client 들은 ACK 이 server 에 도착하는 순서대로 pop 되어 socket 을 할당받고, read / write 를 수행할 수 있게 된다.
- 만약 큐의 크기보다 훨씬 많은 수의 연결 요청이 동시에 들어온다면, 큐가 포화되어 제대로 된 서비스가 불가능 할 것이다. 이를 SYN flooding 이라고 하며, DoS (Denial of Service) 공격의 한 방식이다.
- 정상적이지 않은 client 가 임의의 IP 주소를 단 SYN 들을 엄청나게 많이 보내 queue 를 포화시켜 정상적인 서비스를 방해한다.
- 한 link 를 통해 DoS 공격을 하면 감지가 쉽기에, 여러 link 를 이용하는 방법을 D-Dos (Distiributed DoS) 라고 한다.
Error Control
- ACK 에 대한 ACK 은 없기에, 상대가 정보를 받았는지 guarantee 할 수 없다.
- TCP 는 신뢰성을 보장하기 위해 3 가지 방식으로 ACK 의 갯수를 줄이려고 노력한다.
- 데이터 수신 후 ACK 을 보낼 떄, ACK 만 따로 보내지 않고 sending buffer 의 데이터와 ACK 을 함께 보낸다.
- 데이터 도착 후 sending buffer 에 데이터가 들어올 때까지 일정 시간 대기한다. sending buffer 가 차지 않으면 그냥 ACK 을 보낸다.
- 2 의 경우에서 대기 중 다른 데이터가 도착하면 바로 ACK 을 보낸다. 이 때, 두 데이터에 대한 ACK 을 한번에 보낸다. 최대 2 개의 packet 에 대해 하나의 ACK 을 보낼 수 있는 것이다.
- 데이터 전송 시 packet 이나 ACK 이 유실되는 경우가 있을 수 있다.
- 이 경우는 응급상황이므로, 몇 가지 규칙에 따라 ACK 을 곧바로 보내준다.
- TCP 는 순서가 보장된 데이터만 사용한다. 그만큼 packet loss 에 민감하다. packet loss 는 timer 를 이용해 감지한다. packet 에 timer 를 달아 timer 가 끝나는 time out 까지도 응답을 받지 못하면, packet loss 상황으로 간주한다.
- 그림에서 701 - 800 의 packet 이 유실되고, 801 - 900 의 packet 은 제대로 전송된다. reciever 에서 packet loss 를 감지하면, 유실된 packet 의 자리를 buffer 에 남겨두고 나머지 packet 을 저장한다. 그 후, 곧바로 유실된 packet 에 대한 ACK 을 보내준다.
- ACK 을 받고 sender 가 유실되었던 packet 을 다시 보낸다. 이가 제대로 도착하면, reciever 는 비워두었던 공간을 채우고 ACK 을 보낸다. 이때 ACK 은 유실되었던 packet 이 아닌 가장 끝에 저장된 packet 의 다음 packet 에 대한 것이다.
Fast Retransmission
- 그림에서 301-400 packet 이 유실되었고, rule 4 에 의해 유실된 packet 에 대한 ACK 이 전송되었다.
- flow control 에 의해 sender 는 보낸 데이터에 대한 ACK 을 받지 않아도 window size 가 허락하는 만큼 데이터를 계속해서 보낸다.
- 보내고 있는 데이터가 아닌 유실되었던 301 - 400 packet 에 대한 ACK 이 반복적으로 도착한다. 아직 유실된 packet 을 재전송하지 않았기 때문이다. 같은 ACK 이 3번 반복해 도착한다면, time out 이 되지 않았어도 sender 는 packet loss 가 일어났음을 유추할 수 있다.
- 이 방법으로 time out 전에 빠르게 packet loss 를 감지하는 것을 fast retransmission 이라 한다.
- cumulative ACK 이용 시 fast retransmission 의 구현이 쉽고, ACK 의 갯수를 줄일 수 있다는 장점이 있다.
Lost Acknowledgement
- packet 이 아닌 ACK 이 유실되는 경우도 있다.
- ACK 701 이 유실되었지만, 이후의 ACK 901 에 의해 601 - 700 packet 이 잘 도착해 이후의 데이터 전송이 잘 이루어지고 있었음을 sender 는 알 수 있다.
- 이 경우 무리 없이 데이터 전송을 이어나갈 수 있다. 이것도 cumulative ACK 의 장점이다.
- 하지만, time out 이전에 ACK 이 도착하지 않으면 문제가 생긴다.
- ACK 701 이 유실되어 time out 이전에 응답이 도착하지 않은 상황이다.
- packet 전송은 제대로 이루어졌으나, sender 는 time out 에 의한 packet loss 상황으로 간주한다.
- 이로 인해 sender 는 중복된 packet 을 보낸다.
- reciever 는 이러한 중복된 packet 을 받으면, ACK 을 다시 전송해준다. (Rule 6)
Perisistence Timer
- Cumulative ACK 을 사용했는데도 ACK 유실이 큰 문제를 일으키는 경우가 있다.
- reciever 가 buffer 공간 부족으로 rwnd 0 을 보낸 상황을 가정하자. 이후 read 로 인해 buffer 에 공간이 남아 ACK 에 rwnd k ( k > 0 ) 을 보냈는데, 이 ACK 이 유실된 것이다.
- sender 는 이 ACK 을, reciever 는 packet 을 기다리는 deadlock 이 발생하게 된다.
- 이를 방지하기 위해 persistence timer 가 사용된다.
- rwnd 0 을 받으면, persistence timer 가 돌아간다. timer 가 만료되면, header 낭비를 감수하고 작은 크기의 packet 인 probe segment 를 보낸다. 이는 ACK 을 받아 유실을 방지하고, window size 를 파악하기 위함이다.
Congestion Control
- 위 그림처럼 들어오는 데이터가 나가는 데이터보다 많으면, 혼잡 (병목 현상)이 발생한다.
- 혼잡이 일어날 경우 buffer 에 담지 못해 버려지는 packet 들이 생긴다.
- 혼잡은 중앙 제어가 없는 packet switching network 에서 발생한다. circuit switching network 는 혼잡이 잘 발생하지 않지만, 많은 데이터를 한번에 보낼 수 없다.
- Flow control 은 network 상태를 배제하고 rwnd 만을 고려하기 때문에, sender 측에서 네트워크 내의 데이터 트래픽 상태를 고려하여 데이터의 전송 속도를 조절하는 메커니즘이 필요한데, 이를 congestion control 이라고 한다.
- 유입되는 데이터가 buffer 의 capacity 에 근접할수록, 데이터 전송의 delay 는 exponentially 증가한다.
- throughput 은 데이터를 받아 처리하는 recieving rate 이다.
- 혼잡이 일어나면, buffer capacity 를 초과한 packet 들은 유실된다. sender 는 이를 packet loss 로 인식하고, 유실된 packet 들을 재전송한다. 이 과정에서 같은 양의 packet 을 받는데 걸리는 시간이 증가해 capacity 이상의 데이터를 받을 때 throughput 이 감소하게 된다.
- window size 는 rwnd 와 cwnd 중 작은 값으로 결정된다.
- cwnd (congestion window) 는 sender 가 보낼 수 있는 데이터에 대한 정보다.
- cwnd 가 0이면 데이터 전송 자체가 모순이기 때문에, 최소값은 1이다.
Congestion Avoidance, Additive Increase
- 혼잡 구간이 아닌 곳에서 보내는 데이터의 양을 조금씩 늘려가며 혼잡이 일어나는 구간을 찾아가는 과정이다.
- 그림에서 첫 cwnd 가 4로 설정되어 있다. 보낸 packet 의 크기만큼 ACK 이 왔으므로, 혼잡 없이 데이터 전송이 성공적으로 이루어짐을 알 수 있다.
- 혼잡 구간을 알아내기 위해 cwnd 를 조금씩 늘려가며 데이터를 보낸다. 늘리는 기준은 모든 ACK 이 도착하는 시간인 RTT (round trip time) 마다 1씩 늘리는 것이다.
- 이 과정을 반복하다가 혼잡이 발생하면, cwnd 를 반으로 줄여 계속 시도한다.
- 하지만, 모든 상황에서 additive increase 만을 사용하는 것은 너무 느리다.
Slow Start, Exponential Increase
- rwnd 가 충분히 커, window size 에 영향을 미치지 않는 상황을 가정한다.
- 모든 ACK 이 돌아왔을 때, 1씩이 아닌 두 배로 늘리는 방법이다.
- 이름이 slow start 인 이유는 처음부터 window size 만큼 보내는 flow control 에 비해 시작이 느리기 때문이다.
- exponential increase 가 혼잡에 가까워졌다고 판단해 멈추고 additive increase 로 전환하는 시점은 두 가지이다.
- cwnd 가 정해진 threshold 에 도달함
- pocket loss 가 감지됨
TCP Congestion Policy
- congestion control 의 과정을 정리하자면 다음과 같다.
- 처음에는 slow start 를 통한 exponential increase 를 진행한다. threshold 에 다다르면 congestion avoidance 로 바로 전환한다.
- 3 duplicate ACK 이 도착하면 packet loss 가 일어나 fast retransmission 을 보낸다. packet loss 의 대부분은 혼잡에 의해 일어나기 때문에 3 duplicate ACK 은 혼잡으로 간주할 수 있다.
- slow start 나 congestion avoidance 에서 3 duplicate ACK 이 감지되면, cwnd 를 반으로 줄여 다시 congestion avoidance 를 실행한다.
- packet loss 에는 time out 에 의한 경우도 있었다. 이는 3 duplicate ACK 와는 달리 다수의 packet 에서 문제가 발생한, 긴급 상황이다. 이 경우네는 cwnd 를 1, threshold 를 window size 의 절반으로 설정해 slow start 를 실행한다.
- 이를 그래프로 나타내면 다음과 같다.
- 위와 같이 AI 와 MD 를 번갈아가며 혼잡제어를 하는 방법을 AIMD 라고 한다.
Why is TCP Fair?
- TCP 는 중앙제어 없이도 혼잡제어를 잘한다.
- RTT 가 같은 두 session 을 가정하자.
- 좌상향하는 선은 x + y = R 즉, 혼잡이 일어나는 경계다.
- 혼잡 상황 전의 한 점에서 AIMD 를 반복하며 혼잡 제어를 하다 보면, 두 session 이 트래픽을 동등하게 나눠 갖는 equal bandwidth share 선에 수렴한다.
- 즉, TCP 의 혼잡제어는 fair 한 것이다.
TCP Timers
Keepalive Timer
- 여기서는 아직 언급되지 않은 keepalive timer 에 대해서 서술한다.
- 오랜 기간 동안 idle 상태에 있는 것을 방지한다.
- 이 경우, 상대가 데이터를 보내지 않는 것인지, 오류가 생겨 terminate 된 건지 알 수 없다.
- 이를 위해 서버가 클라이언트로부터 2시간 동안 데이터를 받지 못하면, probe segment 를 보내 확인한다.
Retransmission Time Out
RTO
- RTO 를 결정하는 방법에 대해서 알아보자
- 첫 RTO 는 초기에 system 에서 정해준 값을, 이후에는 위 공식을 사용한다.
- RTTs 는 측정값의 평균, RTTd 는 편차를 의미한다.
Smoothed RTT
- 측정값의 평균인 RTTs 를 결정하는 방법을 살펴보자.
- RTTs 는 이전 측정의 평균치, RTTm 은 새로 측정된 값이다.
- a 가 1/8 인 이유는 새로 측정된 값에 가중치를 덜 두기 위함이다.
=> 이렇게 가중치를 두어 평균을 구하는 방식을 moving average 라 한다.
RTT Deviation
- 편차값은 RTTd 를 구하는 방법에 대해서 알아보자.
- 위 측정 방법들을 토대로 시간대 별 RTO 결정 과정을 살펴보자.
- 첫 RTO 값은 system 이 정해준 대로 사용
- 첫 측정에서 :
1. RTTm 은 측정값
2. RTTs 는 RTTm 과 같은 값
3. RTTd 는 Rttm 의 절반
4. RTO = RTTs + 4RTTd
- 이후의 측정에서는 앞의 공식들을 사용한다.
- 혼잡으로 인해 packet 이 예상보다 늦게 도착할 수 있어, RTTm 에 비해 RTO 를 여유롭게 잡는다.
Karn's Algorithm
- 위의 두 경우는 timeout 으로 인해 packet loss 로 간주되는 상황이다.
- packet loss 를 예측한 sender 는 packet 을 재전송한다.
- (a) 는 실제 packet loss, (b) 는 혼잡으로 인해 timeout 이후에 ACK 이 도착한 경우다.
- 이 때, transmission 시작점을 기준으로 RTT를 계산하면, (a) 와 (b) 에서의 값에 차이가 생기는데, sender 의 입장에서는 두 경우를 구분할 수 없어 오류가 생긴다.
- 이 오류를 해결하는 방법이 Karn's Algorithm 으로, 두 가지 원칙이 있다.
1. re-transmission 은 RTT 계산에서 고려하지 않는다.
2. 정상적인 packet 에 대한 ACK 도착 시에만 측정을 시작한다.
- 이를 적용한 예시를 살펴보자
- time out 이후 재전송 시에는 RTO 값을 두 배로 늘린다. => exponential backoff
- 정상적인 ACK 도착 시점에서부터 RTT 측정을 시작한다. => Karn's algorithm
OPTIONS
- TCP header 는 40 byte 까지의 option 을 가질 수 있다.
- optinon 의 길이에 따라 single byte, multiple byte 로 구분된다.
- option 의 앞에 kind 값으로 option number 를, length 값으로 길이를 표시한다.
End of Option (EOP)
- single byte option 이다.
- header 의 한 줄의 길이는 4 byte 인데, 3 byte option 이 이용될 시 뒤의 공백을 채운다.
- EOP 는 header 당 한 번만 쓰일 수 있다.
No-Operation (NOP)
- single byte option 이다.
- EOP 와 유사하나, 앞의 공백을 채울 때 사용한다.
- EOP 와 달리 header 당 여러 번 쓰일 수 있다.
Maximum Segment Size
- 기본으로 설정된 MSS 의 크기를 변경할 때 사용된다.
- 이 크기 변화는 연결 setup 과정에서 sender, reciever 간의 합의 하에 한 번 이루어질 수 있다.
Window Scale Factor
- window size 를 2의 거듭제곱 배로 늘릴 때 사용된다. n 을 저장하면 2^n 배 늘린다.
- MSS 와 마찬가지로 setup 과정에서 한 번 설정될 수 있다.
- 왜 window size 를 늘리는 option 이 필요할까?
- RTT 가 1초인 상황을 가정한 것이다.
- 2^16 은 표현할 수 있는 window size 의 최대 크기인데, 이만큼 데이터를 보낸다 해도 0.5Mbps 의 속도밖에 나지 않는다.
- RTT 가 10배로 줄어 속도가 5Mbps 가 되어도 이는 부족한 숫자다.
- 그러므로, scaling factor 를 사용해 window size 를 늘려 데이터 전송 속도를 확보하는 것이다.
Timestamp
- 어떤 packet 이 전송되기 시작한 시점을 저장한다.
- 이를 이용하면 RTT 를 빠르게 구할 수 있다.
- 또한, 데이터 전송이 길어져, 같은 seq number 를 가지는 packet 들이 생겼을 때, 이들을 구분하는 기준이 될 수도 있다.
=> 이를 Protection Against Wrapped Sequence Number (PAWS) 라 한다.
SACK
- cumulative ACK 은 packet loss 이후의 packet 들의 상태를 한 번에 알 수 없어, 이후 packet 들을 한꺼번에 재전송해야 한다는 단점이 있다. 이를 보완하기 위한 것이 SACK option 이다.
- SACK-permitted option 에서 sender 와 reciever 간의 동의가 이루어지면 사용 가능하다.
- 2001:3000, 3001:4000, 6001:7000, 7001:8000 packet 이 유실된 상황이다.
- reciever 은 받은 packet 들을 block 으로 묶고, block 의 시작 seq num 과 끝 seq num + 1 의 값을 SACK 에 저장한다.
- 이렇게 저장한 SACK option 값으로 전송이 완료돼 재전송이 필요없는 packet 들을 구분할 수 있다.
- 이 option 은 on / off 가 가능하다.