## 1. transport-layer의 서비스와 프로토콜
![[Transport Layer - transport layer abstraction.png|center|400]]
- 서로 다른 호스트에서 **실행되는 application(= process)** 간의 논리적인 통신을 제공함
- 네트워크 계층은 호스트 간, 트랜스포트 계층은 프로세스 간 논리적 통신을 제공함
![[Transport Layer - protocol data unit.png|center|300]]
- 이 계층의 프로토콜(TCP, UDP)은 엔드 시스템에서 동작함
- **sender**: application 계층의 메세지를 **segments**로 나눠서 네트워크 계층으로 보냄
- segment 필드의 값을 결정하고 segment를 만듦
- **protocol data unit = PCI(protocol control information, 우리 프로토콜을 다루기 위한 정보) + SDU(service data unit, 전달할 메세지)**
- **receiver**: segments를 다시 모아서 application layer로 보냄
- 헤더 값을 확인한 후 application 계층의 메세지만 추출함
- demultiplex를 통해 데이터를 송수신하는 과정에서 다중화된 데이터를 해당하는 응용 프로그램으로 분리하여 소켓을 통해 전달함
<br><br>
**Transport 계층의 프로토콜 : TCP와 UDP**
- **TCP: Transmission Control Protocol**
- reliable, in-order delivery : 신뢰할 수 있는 연결, 순서대로 전송됨
- congestion control
- flow control
- connection setup
- **UDP: User Datagram Protocol**
- unreliable, unordered delivery : 데이터 손실될 수도 있고 도착 순서가 보장되지 않음
- no-frills extension of "best-effort" IP : 간단하고 직접적인 데이터 전달을 목적으로 하며, 신속한 통신이 중요한 경우에 유용
<br><br>
**멀티플렉싱과 디멀티플렉싱**
![[Transport Layer - multiplexing and demultiplexing.png|center|300]]
- **멀티플렉싱(multiplexing)**
- 다수의 소켓으로부터 들어온 데이터를 다룸
- 추후 상대 host의 demultiplexing을 돕기 위한 **transport header**를 추가함
- **디멀티플렉싱(demultiplexing)**
- host는 통신의 결과로 **IP 데이터그램**을 수신함
- 각 데이터그램은 출발 호스트의 IP 주소와 목적지의 IP 주소를 포함함
- 각 데이터그램은 하나의 트랜스포트 계층 세그먼트를 들고있음
- 각 세그먼트는 송신, 수신 측의 포트 넘버를 가지고 있음
- 올바른 소켓에 세그먼트를 전송하기 위해 받은 **헤더(IP 주소와 포트 넘버)**를 사용함
- UDP의 디멀티플렉싱에서는 **목적지의 포트 넘버만** 사용함
- UDP 소켓에서는 목적지의 IP 주소도 사용함
- TCP의 디멀티플렉싱은 **4개**의 튜플을 사용함 (**송수신 IP 주소, 포트 넘버**)
- 멀티플렉싱과 디멀티플렉싱은 모든 계층에서 일어남
<br>
> **Data Link 계층에서 reliable data transfer 프로토콜을 제공한다고 해도, Transport Layer에서도 제공해야 함**
>
> 1. **데이터 링크 계층에서의 신뢰성은 트랜스포트 계층의 신뢰성과는 별개임.**
> 네트워크 계층은 호스트 간, 트랜스포트 계층은 프로세스 간 논리적 통신을 제공함
> 2. **Transport Layer의 reliable data transfer 은 오류 복구와 흐름 제어 기능을 포함함.**
> 데이터 링크 계층에서의 신뢰성은 일반적으로 물리적인 오류(예: 비트 오류)에 대한 복구를 다루며, Transport Layer의 신뢰성은 네트워크 내의 다양한 오류(예: 패킷 손실, 지연)에 대한 복구를 다룸
>
> 데이터 링크 계층에서의 reliable data transfer 프로토콜은 물리적인 링크 상에서의 신뢰성을 제공하지만, Transport Layer에서의 reliable data transfer는 더 넓은 범위의 네트워크 오류에 대응하여 end-to-end 신뢰성을 보장함
<br><br><br>
## 2. UDP : connectionless transport
<br>
**UDP 개요**
- 날 것의, 부가적인 기능이 없는 트랜스포트 프로토콜
- "best effort" 서비스 : 데이터 손실될 수도 있고 도착 순서가 보장되지 않음
- best effort service : “send and hope for the best”
- **connectionless 함**
- 송수신인 간의 handshaking 과정이 없음
각 UDP 세그먼트는 다른 것과 독립적으로 다뤄짐
- **UDP의 장점**
- connection 과정이 없으니까 RTT 딜레이가 TCP에 비해 적어짐
- 연결 상태에 대한 것도 없어서 심플함
- 헤더 사이즈가 TCP에 비해 작음
- congestion control이 없음
- 응용 프로그램에서 원하는 속도로 데이터를 빠르게 전송 가능함 → 스트리밍 서비스에서 주로 활용됨
- congestion에 영향을 받지 않음
- UDP를 쓰면 reliability와 congestion control을 application 계층에서 보장해줘야 함
- e.g. HTTP/3 : HTTP/2 + QUIC
- **HTTP/3는 TCP 대신에 UDP 위에 구축된 QUIC(Quick UDP Internet Connections) 프로토콜을 사용**
<br><br>
**==UDP의 segment header==**
![[Transport Layer - UDP의 segment header.png|center|300]]
- source port #: 송신인 포트 넘버
- destination port #: 수신인 포트 넘버
- length: 길이
- **checksum**: **데이터 수신 시 에러 여부 체크용 (error detection, redundancy)**
- 헤더의 데이터 또한 함께 체크함
- application data
<br><br><br>
## 3. reliable data transfer(RDT)의 원리
- ==네트워크는 unreliable함 (best effort service) → **reliable한 데이터 전송을 위해서는 transfer 프로토콜이 필요함**==
- 송수신 측은 메세지가 잘 갔는지 상태를 확인하기 위해 메세지를 주고받아야 함
![[Transport Layer - reliable data transfer(RDT).png|center|500]]
- **rdt_send()**: 응용 프로그램이 전송할 데이터를 rdt_send()에 전달하면 데이터를 수신자의 상위 레이어에 전달함
- **udt_send()**: rdt_send()에 의해 호출되며, 신뢰할 수 없는 채널을 통해 패킷을 수신자에게 전송함
- rdt_send()에서 안정적으로 전송되어야 할 데이터를 udt_send()가 전송 가능한 형태로 채널에 보냄
- **rdt_rcv()**: 이 함수는 수신자 측에서 채널을 통해 패킷이 도착했을 때 호출됨
- 수신된 패킷을 처리하고 필요한 오류 검사 및 복구 등의 작업을 수행함
- **deliver_data()**: rdt_rcv()에 의해 호출되며, 상위 레이어에 데이터를 전달함
- 수신자가 정상적으로 패킷을 받고 처리한 후에 데이터를 상위 레이어에 전달하기 위해 사용됩니다.
<br><br>
**rdt1.0: reliable transfer over a reliable channel**
![[Transport Layer - rdt1.0 - reliable transfer over a reliable channel.png]]
- 채널에 에러가 없다면 비트 에러도 없고 패킷 로스도 없음
- FSM을 송신자와 수신자로 나눔
- 송신자는 채널로 데이터를 보내고 수신자는 채널로부 터 데이터를 받음
<br><br>
**rdt2.0: channel with bit errors**
- 채널에 에러가 없을 수는 없음
- 에러를 체크하기 위해 **checksum**을 사용함
- 전송 중에 에러가 있었다는 것을 알기 위해 **ACK과 NAK**을 활용함
- ACKs(Acknowledgements) : 수신자가 송신자에게 패킷이 무사히 도착했음을 알리는 응답
- NAKs(negative acknowledgements) : 패킷이 에러가 있다고 알리는 응답
- 이 경우 송신자가 패킷을 다시 전송함
> **stop and wait**
> 송신자가 하나의 패킷을 보낸 후 수신자의 응답을 기다림
![[Transport Layer - rdt2.0 - channel with bit errors.png|center|500]]
- 송신자: 데이터를 기다리고 ACK/NAK을 기다리도록 상태를 바꿈
- NAK을 받으면 데이터를 재전송함
- 수진자: 데이터가 무사히 도착했으면 ACK을, 아니면 NAK을 보냄
- ACK의 경우에만 패킷에서 데이터를 추출해서 상위 레이어에 전달함
- **문제점**
- ACK/NAK이 전송에 실패했을 때
- **송신자는 무슨 일이 생긴 줄 모름**
- 무작정 보냈다가는 중복해서 데이터를 보낼 수도 있음
<br><br>
**==rdt2.1: sender, handling garbled(혼동된) ACK/NAKs==**
- 송신자는 각 패킷에 **==sequence number==**를 추가함. 이걸 통해 수신자는 중복된 패킷인지 구분함
- **송신자**
![[Transport Layer - rdt2.1 - sender, handling garbled(혼동된) ACK,NAKs.png]]
- 패킷에 seq# 추가
- 2개의 시퀀스만 있어서 0, 1로도 충분함
- ACK/NAK 응답 주의하기
- seq#가 제대로 왔는지도 항상 주의해야 함
- **수신자**
![[Transport Layer - rdt2.1 - receiver, handling garbled(혼동된) ACK,NAKs.png]]
- seq# 를 통해 패킷이 중복됐는지 체크해야 함
- 여전히 수신자는 내가 보낸 ACK/NAK이 제대로 갔는지 모름
<br><br>
**rdt2.2: a NAK-free protocol**
- NAK도 추가 메모리라 아까운데, NAK 없이 데이터 수신을 확인할 수 없나?
- ACK을 보내되, **ACK에도 받은 패킷의 seq#를 포함시키면 됨**
- 이렇게 하면 송신자가 어떤 패킷을 재전송해야 하는지 정확히 알 수 있음
- 송신자가 ACK를 받았지만 여러 번 중복되어 도착하는 경우에도 현재 패킷을 재전송함
- TCP가 이렇게 사용함
![[Transport Layer - rdt2.2 - a NAK-free protocol.png|center|600]]
<br><br>
**==rdt3.0: channels with errors and loss==**
- 에러 뿐만 아니라 버퍼 오버플로우 등의 이유로 **packet loss**(data, ACK)도 생길 수 있음. loss는 어떻게 다루지?
- **타임아웃, timeout**
- 송신자는 resonable한 시간(RTT, round trip time을 잘 산정한 시간)만큼 ACK을 기다림
- 만약 이 시간 내에 ACK이 오지 않으면 패킷을 다시 전송함
- loss가 아니고 그냥 늦은 거였다면 패킷 전송이 중복되지만, 이는 seq#를 통해 구분 가능함
![[Transport Layer - rdt3.0 - channels with errors and loss.png|center|600]]
- ==리시버의 경우는 어떨지 고민해보기==
![[Transport Layer - rdt3.0 - channels with errors and loss 2.png]]
- **rdt3.0(stop-and-wait)의 성능**
![[Transport Layer - performance of rdt3.0.png|center|600]]
- stop-and-wait 방식은 결국 RTT동안 데이터를 1개만 보냄 → **비효율적임**
- t(초) = RTT + L/R
- U = (L/R) / RTT + L/R = 0.008 / 30.008 = 0.00027
<br><br>
**rdt3.0 ==pipelined protocols operation== (continuous repeat request)**
- **pipelining**: ACK 없이 한꺼번에 많은 양의 데이터를 보내는 걸 허용함
- seq#가 보다 더 많이 필요해짐
- 송신자와 수신자에 버퍼링이 생김
> **window size**: sliding window protocol에서 보내는 쪽과 받는 쪽에서 **ACK 없이 보낼 수 있는 패킷의 개수**
![[Transport Layer - Go-Back-N and Selective repeat.png]]
- ==**Go-Back-N**==
- **cumulative ACKs**: 수신자가 시퀀스 번호 5까지의 패킷을 정상적으로 받았다고 가정하면, "cumulative ACK 5"는 수신자가 패킷 5까지를 모두 성공적으로 수신했다는 것을 나타냄
- window size가 4일때, timeout이 seq# 2에서 발생하면 2번 패킷부터 시작하여 2, 3, 4, 5의 4개의 패킷을 전송함
- 장단점
- 작업이 단순하지만 패킷이 중복되는 단점이 있음 (n번 이후로 다 다시 재전송하니까)
- 수신 측에서는 빠진 데이터 이후 데이터를 버퍼링 할 필요가 없어서 좋음
- ==**Selective repeat**==
- window size가 4일때, timeout이 seq# 2에서 발생하면 2번 패킷만 재전송함 → 2, 4, 5, 6의 4개의 패킷을 전송함
- 수신자가 버퍼에 3번 패킷을 저장했다가 2번 패킷을 받은 후 패킷을 순서대로 다시 조합 해야 함
- 장단점
- Go-Back-N에 비해 상대적으로 복잡함, 버퍼가 커야 함
![[Transport Layer - selective repeat dilemma.png|center|500]]
- 두 방법 다 윈도우 사이즈와 시퀀스 넘버 간의 관계가 중요함. 잘 설정해야 함.
<br><br><br>
## 4. TCP : Connection-oriented transport
### 4-1. TCP 개요
<br>
**TCP의 특징**
- **point-to-point**: 송신자와 수신자가 1:1 매핑됨
- **reliable**, in-order byte stream: 안전성이 보장됨
- **full duplex** data: 양쪽 다 송수신이 가능함
- **cumulative ACKs**
- **pipelining**: TCP congestion과 flow control에서 window size를 설정함
- **connection-oriented**: handshaking을 통해 송수신 간의 초기 설정이 필요함
- **flow controlled**: 버퍼 상태를 고려함
<br><br>
**==TCP segment structure==**
> **TCP의 전송단위는 segment, 크기는 MSS(Maximum Segment Size)**
> **TCP의 헤더 길이는 가변적임**
![[Transport Layer - TCP segment structure.png|center|500]]
- source port # : 송신인 포트 넘버
- destination port # : 수신인 포트 넘버
- **sequence number** : segment seq#임. 바이트 스트림 상에서 데이터의 위치를 나타냄
- **acknowledgement number**
- head len : TCP 헤더의 길이
- not used
- C, E : congestion nofification
- U
- A : **piggy backing** 여부 (데이터랑 ACK 같이 보냄요), 1이면 ACK도 처리하라는 의미임
- P
- R : Reset, 1이면 커넥션을 재설정함
- S : 세션 열기 요청
- F : Finish, 1이면 통신을 그만하자는 의미임, close() 함수를 호출하고 관련 리소스를 해제함
- **receive window** : flow control에 사용됨, 수신자가 수신할 수 있는 바이트 크기
- checksum : 데이터 수신 시 에러 여부 체크용 (error detection, redundancy)
- 헤더의 데이터 또한 함께 체크함
- urg data pointer
- options (variable length) : 여러 TCP 옵션들 (e.g. 보내는 시간 정보 등등)
- application data (variable length) : TCP 소켓을 통해 응용프로그램이 보낸 데이터
<br><br>
### 4-2. TCP의 RTT와 타임아웃
- **타임아웃을 설정할 때는 보통 RTT보다 길게 설정해야 함**
- 너무 짧으면 불필요한 재전송이 생김, premature timeout
- 너무 길면 segment loss에 늦게 반응함
- EstimatedRTT = (1 - α) * EstimatedRTT + α * SampleRTT
- exponential weighted moving average (EWMA)
- 보통 α = 0.125 임
- application으로부터 데이터를 받으면
- **seq#**를 가지고 segment로 쪼갬
- seq#는 바이트 스트림 상에서 데이터의 위치를 나타냄
- 송신자는 ACK를 기다리는 중인 패킷에 대한 타이머를 시작함 (타이머가 이미 실행중이 아니라면)
- 송신자는 가장 오래된 확인되지 않은 패킷에 대한 타이머를 시작하여 해당 패킷의 ACK를 기다림
- 이렇게 함으로써 송신자는 가장 이전에 전송한 패킷의 재전송을 관리하고, 데이터의 신뢰성을 유지함
- **타이머의 만료 간격은 TimeOutInterval로 설정됨**
- 이때 타임아웃이 발생하면 타임아웃을 발생시킨 segment를 재전송하고 타이머를 다시 시작함
- 이때 기다리던 ACK이 도착하면 해당 segment를 ACked로 업데이트하고 다른 unACKed segment에 대해 타이머를 시작함
<br><br>
**TCP 수신자 측 이벤트와 반응(ACK 응답)**
![[Transport Layer - TCP 수신자 측 이벤트와 반응(ACK 응답).png|center|500]]
1. **예상 seq#, 정확한 순서**
- 이미 기대하는 seq#까지 모든 데이터를 확인해서 Delayed AC을 보냄
- 이 경우, 다음 세그먼트를 기다리는 동안 최대 500ms를 기다린 후에 ACK을 보냄
- 그러나 다음 세그먼트가 도착하지 않으면 바로 ACK을 보냄
2. **예상 seq#, 다른 세그먼트에 대한 ACK 대기중**
- 이미 확인되지 않은 다른 세그먼트에 대한 확인이 보류중이라 해당 세그먼트와 함께 하나의 cumulative한 ACK을 즉시 보냄
- 이렇게 함으로써 두 세그먼트 모두 확인할 수 있어짐
3. **예상 seq#가 아님**
- 기대하던 seq#보다 높은 seq#를 받으면, 이전에 수신한 패킷보다 높은 번호의 패킷이 도착한거임
- 이 경우, 현재까지의 세그먼트 중 누락된 부분을 가리키는 Duplicate ACK을 즉시 보냄
4. gap..
![[TCP - retransmission scenarios.png|center|600]]
<br><br>
**TCP fast retransmit**
![[Transport Layer - TCP fast retransmit.png|center|500]]
- **세 번의 중복된 ACK는 송신자에게 데이터의 손실을 알려줌**
- 일반적으로, 이는 수신자가 해당 데이터를 수신하지 못했거나 처리하지 못했음을 의미함
- 따라서 송신자는 세 번의 중복된 ACK를 받으면, 해당 데이터의 손실을 가정하고 즉시 해당 데이터를 재전송함
- 일반적으로 데이터의 손실을 감지하고 재전송하기 위해 TCP는 타임아웃을 사용함
- 그러나 ==세 번의 중복된 ACK를 받으면, **이는 데이터의 손실을 명확히 나타내므로 타임아웃을 기다리지 않고 즉시 데이터를 재전송 함**==
<br><br>
### 4-3. Flow Control
- 만약 네트워크 계층이 데이터를 전달하는 속도가 application 계층에서 소켓 버퍼를 비우는 속도보다 빠르다면?
1. 버퍼 오버플로우 발생: 소켓 버퍼에 쌓이는 데이터가 너무 많아지면 버퍼 오버플로우가 발생할 수 있음. 이는 버퍼의 용량을 초과하여 데이터가 손실되는 상황을 의미함
2. 응답 지연: 소켓 버퍼가 과도하게 쌓이면 응용 프로그램이 데이터를 처리하는 데 걸리는 시간이 증가할 수 있음
3. 메모리 사용량 증가: 과도한 버퍼링은 시스템 자원을 낭비하게 됨
4. 네트워크 혼잡: 소켓 버퍼가 가득 차면 네트워크 혼잡을 초래할 수 있음
![[Transport Layer - TCP segment format - flow control.png|center|250]]
- ==**flow control**==
- ==송신자가 너무 빠르게 데이터를 전송하여 수신자의 버퍼를 넘치게 하는 상황을 방지하기 위한 메커니즘==
- **흐름 제어는 수신자가 송신자를 명시적으로 제어할 수 있도록 함**
- 수신자가 송신자에게 데이터를 너무 많이 또는 너무 빨리 보내지 않도록 조치할 수 있게 해줌
- = 송신자가 수신자의 버퍼를 너무 많은 데이터로 채우지 않도록 함
- 이는 송신자가 데이터를 너무 빠르게 전송하여 수신자의 버퍼가 오버플로우되는 상황을 방지함
- 수신자가 **TCP 헤더의 ==rwnd(receive window)==**를 이용해서 수신 버퍼의 여유 공간을 송신자에게 알려줌
- 대다수의 운영 체제가 수신 버퍼의 크기를 자동으로 조정함 (일반적인 기본값은 4096 바이트)
- 송신자는 수신자가 "rwnd" 필드에 표시한 수신 버퍼의 여유 공간에 따라 데이터를 전송함
- 만약 수신자의 버퍼가 가득 차 있다면, 송신자는 데이터를 전송하지 않고 대기함
<br><br>
### 4-4. TCP의 연결 관리
- 데이터를 보내기 전, 수신자와 송신자는 **'handshake'** 과정을 거침
- 먼저, 송신자와 수신자는 서로 연결을 설정할 의향이 있는지에 대한 동의를 주고 받음
- connection parameter를 통해 합의함 e.g.시작 seq#
- 처음 보내는 seq#는 0이 될 수 있음
<br>
**TCP 2-way handshake**
![[Transport Layer - TCP 2-way handshake.png]]
- half open connection : 타임아웃에 의한 재전송인지 모르고 수신자가 하염없이 기다림
<br><br>
**==TCP 3-way handshake==**
![[Transport Layer - TCP 3-way handshake.png]]
![[Transport Layer - TCP 3-way handshake FSM.png|center|500]]
<br><br>
**TCP 연결 끊기**
![[Transport Layer - Closing a TCP connection.png]]
<br><br>
**4 WAY FIN**
![[Transport Layer - Closing a TCP connection - 4 way fin..png]]
<br><br><br>
## 5. ==congestion control==
> congestion control는 네트워크 전체의 혼잡을 관리하고 제어하여 패킷 손실을 최소화하고 네트워크 성능을 유지하는 데 중점을 두는 반면, flow control은 수신자와 송신자 간의 특정 연결에서 발생하는 데이터 흐름을 관리하여 효율적인 데이터 전송을 보장함**
<br>
- 너무 많은 송신측이 너무 많은 데이터를 너무 빨리 보내서 **네트워크가 이를 수용할 수 없는 상황을 의미함**
- congestion을 알아채는 단서
- **긴 딜레이 시간 (라우터 버퍼에서 queueing됨)**
- **packet loss 발생 (라우터에 버퍼오버플로우 발생)**
- congestion 발생을 그래프로 그려보자면 다음과 같음 (x축=데이터 유입량, y축=수신되는 데이터의 양)
- ==**congestion이 발생하면 데이터를 보내면 보낼수록 데이터 수신량이 적어지다가 아예 수신을 못 할 수도 있음**==
![[Transport Layer - congestion graph 2.png|center|400]]
<br><br>
**Congestion 다루기**
우선 congestion을 다루는 개체 기준 2가지 방법으로 나뉨
![[Transport Layer - congestion control type.png]]
1. **End-end congestion control**
- **네트워크의 도움 없이** end point에서 본인이 겪는 현상을 바탕으로 congestion을 감지하고 해결하는 접근 방식
- **패킷 손실과 delay 현상**을 통해 congestion 발생을 유추할 수 있음
e.g. 데이터를 보냈는데 ACK이 안 오네. 중간에 loss가 있나보다
e.g. RTT(Round Trip Time)을 계산했는데 현저히 느려졌네. delay가 생겼어
- TCP에서 흔히 사용되는 방법
2. **Network-assisted congestion control**
- 라우터가 congested 라우터에 대한 정보를 송신, 수신 호스트에 직접적으로 알려줌
<br><br>
### 5-1. TCP의 congestion control
![[Transport Layer - TCP의 congestion control.png|center|300]]
**==AIMD(additive increase, multiplicative decrease)==**
> 접근 방식 : 패킷 손실이 발생할 때까지 전송률을 높인 다음 congestion이 발생하면 전송률을 낮추는 방법
- 증가는 조금씩. congestion 감지 시 감소는 팍팍
- **매 RTT마다 loss를 감지할때까지 전송률을 1 MSS (maximum segment size) 사이즈씩 증가시킴**
- **congestion이 발생하면 현재 전송률을 절반 속도로 줄임**
- TCP Reno의 경우, 손실이 감지되면 triple duplicate ACK(세 번의 중복 ACK)가 발생하고 이를 감지하여 전송 속도를 절반으로 줄임
- TCP Tahoe의 경우, 손실이 감지되면 timeout이 발생하고 이를 감지하여 전송 속도를 1 MSS(최대 세그먼트 크기)로 줄임
- AIMD를 선택하는 이유는 네트워크의 congested flow 속도를 최적화하고 원하는 안정성 속성을 가지기 때문
<br><br>
**==slow start==**
![[Transport Layer - slow start.png|center|400]]
- **slow start**
- 먼저 "slow start" 상태에서 시작하여 전송 속도를 지수적으로 증가시킴
- 네트워크 상황을 모르니까 처음에는 cwnd 를 1 MSS로 보냈다가 ACK을 받으면 2배씩 해서 보냄
- exponential하게 커짐 어느 순간 congestion이 감지됨
- **slow start에서 ==congestion avoidance==로 전환**
- congestion avoidance 상태에서는 전송 속도를 **'==linear=='**하게 증가시킴(=additive increase)
- exponential 증가에서 linear 증가로 전환하는 시점
- **cwnd(혼잡 윈도우 크기)가 timeout 이전의 값의 절반에 도달했을 때**
- **구현 방법**
- ssthresh(congestion window 크기의 임계값) 변수를 사용하여 혼잡이 발생했을 때 증가율을 조절함
- **loss가 발생하면 ssthresh는 해당 이벤트가 발생하기 직전의 cwnd 값의 절반으로 설정됨**
![[Transport Layer - TCP congestion control.png]]
<br><br>
**TCP CUBIC**
![[Transport Layer - TCP CUBIC.png]]
- 앞선 방법들은 congestion이 이미 발생한 후의 대처임
- **congestion 전에 방지할 수는 없을까? → loss 말고 delay를 활용해보자**-
![[Transport Layer - TCP CUBIC 2.png|center|400]]
<br><br>
**congested “bottleneck link”**
- TCP는 패킷 손실이 발생하는 지점까지 TCP의 송신 속도를 증가시킴
- 어떤 지점 : bottleneck link
- congested bottleneck link을 알려주면 congestion을 알기 쉬워짐
<br><br>
**TCP fairness**
![[Transport Layer - TCP fairness abstraction.png|center|400]]
- TCP를 뭐쓸지 고를때 고려할 사항
- 모두 공평하게 리소스를 활용할 수 있어야 함
- equal bandwidth share : 제일 공평하게 나눠먹는 지점을 찾아야함
- TCP는 공평한가?
- 이상적인 가정 하에서는 공평함
- 모든 연결이 **같은 RTT(라운드트립 시간)**을 가짐
- congestion avoidance 상태에서의 고정된 수의 세션
![[Transport Layer - TCP fairness.png|center|500]]
<br><br><br><br>