2023. 2. 10. 12:06ㆍ네트워크
Transport Layer
목차
- Transport Layer Services
- Multiplexing and Demultiplexing
- Connectionless Transport : UDP
- Reliable DataTransfer
- Connection-Oriented transport : TCP
Transport Layer Services
- 서로 다른 호스트에서 실행되고 있는 프로세스간의 논리적인 통신을 제공한다.
- 송신측 : 메세지를 세그먼트로 쪼갠 뒤, 헤더 추가해서 네트워크 계층으로 전달
- 수신측 : 네트워크 계층에서 전달받은 데이터그램에서 세그먼트를 추출해 재조립해서 애플리케이션 계층으로 전달
- 네트워크 계층 → 서로 다른 호스트간 논리적인 연결 (IP) 전송 계층 → 서로 다른 호스트에서 실행되는 프로세스간 논리적인 연결 (IP, Port)
- 신뢰성있고, 순서가 있는 전송 → TCP
- 신뢰성없고, 순서를 보장하지 않는 전송 → UDP
- 전송계층의 패킷 = 세그먼트
Multiplexing and Demultiplexing
- 다중화와 역다중화
- 소켓 : 프로세스로 데이터를 전달하기 위한 문, 프로세스마다 여러 개가 있을 수 있다.
- 각 소켓은 유일한 식별자를 가짐
- 다중화 : 여러 소켓으로 부터 온 데이터에 소켓 식별자의 정보를 사용해 전송 헤더를 추가
- 역다중화 : 헤더의 값을 보고 데이터를 전달할 소켓을 식별하여 올바른 소켓으로 데이터 전달
- 소켓의 식별자를 이용해 전송계층 헤더를 생성함 UDP 헤더 → Source Port, Dest Port
- Port 번호 : 16bit - 0~65535 - 0~1023은 예약된 번호
- UDP
- socket(AF_INET, SOCK_DGRAM) : UDP 소켓 생성
- socket.bind((’’, port_num)) : 포트번호 정적으로 할당 → 원랜 자동으로 할당됨
- → dest IP와 dest Port 로 소켓을 식별함 : 도착지 IP, Port 로 소켓 식별함 - 출발지 달라도 다 같은 소켓으로 데이터가 전달됨
- sendto(msg, (IP, PORT))
- recvfrom() : 받은 세그먼트에서 메세지와 출발지의 port 추출
- TCP
- socket(AF_INET, SOCK_STREAM)
- s.listen(1)
- conn, addr = s.accept()
- conn.recv(1024)
- s.connect((IP, PORT))
- s.sendall(msg)
- → Source IP, Source Port, Destination IP, Port 로 소켓 식별, 목적지가 같아도 출발지가 다르면 다른 소켓으로 전달됨
- NMap(Network Mapper) : 네트워크 스캐너, 서버에서 허용된 포트를 확인할 수 있다. = 포트 스캐닝 → 취약한 포트를 확인하는데 쓸 수 있음 (상용서버의 포트를 스캔하면 불법)
Connectionless Transport : UDP
UDP
- UDP 의 세그먼트는 loss 될 수 있고, 순서에 맞지 않게 올 수 있다.
- 사용되는 곳 : 멀티미디어 스트리밍 서비스, DNS, SNMP
- UDP 에서 신뢰성 → 어플리케이션 레이어에서 신뢰성을 제공해야함
- 혼잡 제어 X, 연결 설정 X (→ 연결로 인한 딜레이 없음), 연결 상태를 유지하지 않고 헤더가 작음
- TCP가 늘 UDP보다 좋냐 → 아니다, 애플리케이션 성격에 따라 선택해야함 (일반적으론 TCP 사용)
- 헤더 : data, length, checksum - 에러 체크 용
- Checksum 있는 이유
- 데이터링크 계층에서 에러체크를 제공안할 수도 있음
- 장비가 고장날수도 있고, 라우터의 메모리 오류로 데이터가 발생할 수 있다 → 3계층의 오류를 4계층인 전송계층에서 잡아내기 위함 (보안 기능 X)
Reliable Transmission
- 신뢰성 있는 통신을 제공하기 → 비신뢰 채널을 통해서 신뢰성 있는 통신을 제공하는 법이 필요
- rdt_send() 세그먼트 → udt_send() 패킷 - unreliable channel - rdt_rcv() 패킷 → deliver_data() : 세그먼트
- rdt_send() : 상위 계층에서 데이터 받으면 rdt에 전달
- udt_send() : 신뢰성 있는 프로토콜에 의해 호출, 신뢰성없는 채널을 통해 데이터 전달
- rdt_rcv() : 받은 데이터에 에러 여부 확인하여 상위 레이어로 보냄
- deliver_data() : rdt 통해 받은 데이터 상위레이어 전달
- FSM 유한 상태 기계
Rdt 1.0
- initial state
- sending side : 상위레이어로 부터 오는 데이터 기다림 → 받으면 패킷 만들어 전송
- receving side : 하위레이어로 부터 오는 데이터 기다림 → 받으면 데이터 추출해 상위레이어로 전달
- 비트에러가 없고 & 로스도 없는 경우에만 가능함
rdt 2.0
- 비트 에러를 체크하기 위해 ACK/NACK 추가
- checksum 통해 비트 에러 체크
- ACK : 비트 에러 없는 경우 ACK
- NAK : 비트 에러가 있는 경우 (corrupt() ) NAK 응답
→ ARQ Protocol : Autonomatic Repeat reQuest : 잘받았다/못받았다 응답하는 프로토콜
- Sender side
- Receiver side
→ stop-and-wait 프로토콜 : 송신측에서는 ACK과 NAK 응답 기다리는 동안 상위 레이어에서 데이터 못받음!
- NAK 이 온 경우 재전송함
→ ACK과 NAK에 오류가 있거나/안보내진 경우가 발생할 수 있음
rdt 2.1
- ACK과 NAK이 안보내진 경우가 발생하는 것 방지 → ACK과 NAK에 오류 있으면 재전송 (corrupt 체크) → 각 패킷에 시퀀스 추가 → 수신측에서는 중복 패킷 있을 경우 무시
rdt 2.2
- NAK 제거 → 대신 수신측은 마지막 받은 패킷에 대해서만 ACK을 전송함 ex) 0번 기다리고 있는데 1번에 대한 ACK 오면(마지막으로 받은 패킷이 ACK이라는 뜻) → 0번 패킷 재전송함
- 중복 ACK 발생 → 패킷 재전송
rdt 3.0
- ACK을 기다리고 있는 동안 패킷 로스 발생 → checksum이나 sequence, ACK, 재전송은 Loss 에 대응 불가능
- Timeout을 지정하자 → timeout 이내에 ACK이 오지 않으면 재전송 → loss 된게 아니라 딜레이인데 재전송했어도 - 수신측에서는 기다리고 있던 seq의 패킷이 아니면 상위로 전달하지 않기 때문에 중복 패킷 수신하지 않음
- timeout 되는 경우
- 패킷이 loss 되거나
- 네트워크 상황에 따라 delay가 발생하거나
⇒⇒ 그래도 성능 최악임! stop-and-wait 프로토콜이기 때문에
- 1Gbps 회선, RTT (패킷 보내고 ACK 받는 시간까지의 시간) 30ms, 8000bit 패킷이면
- transmission delay = $D_{trans} = L/R = 8000/10^9 = 8 microsecs$ : 한 패킷의 마지막 패킷을 다 전송 시킬 때까지 8ms 나 걸림
- t = L/R + RTT에 다음 패킷을 보낼 수 있게 됨
- rdt 3.0 의 성능→ 8000 bit (1byte(=8bit) * 1000 = 1KB) 를 30.008ms 마다 보내는건 1기가 속도의 회선에서는 너무 형편없음 - 물리적 자원 사용을 제한하는 속도
- $U_{sender} = (L/R) / (RTT + L/R) = 0.008 / 30.008 = 0.00027$ 이 됨
Pipelining
- stop-and-wait 프로토콜의 성능 문제를 해결하자!
- ACK 오기 전에 여러 패킷을 보내기
- 시퀀스의 범위가 커져야하고
- Sender와 리시버에 버퍼가 있어야한다
- 단점 : 관리하는 시퀀스의 범위가 커져야하고, Sender와 리시버에 버퍼가 있어야한다
- Pipeline으로 네트워크의 Utilization을 향상시킬 수 있다. 세개의 패킷을 보내고 ACK을 기다린다고 했을 때, → 첫번째 패킷의 마지막 bit를 보낼 때 까지 = L/R 걸리고 마지막 패킷의 ACK이 오는 시점은 3 * L/R + RTT 이므로 U = (3 * L/R) / (L/R + RTT) 이므로 3배 향상된다.
Go-back-N
- N개를 보내고 ACK을 기다리는 방식
- N개를 전송하고, 중간에 loss되면 loss 된 패킷 부터 다시 보냄
- 수신자는 cumulative ACK을 전송 - 중간에 수신 안된 패킷이 생기면 갭이 생김 → ACK을 받지 못하게 됨
- 송신자는 가장 오래된 unACKed 패킷에 대해 timer 구동
Selective Repeat
- 중간에 loss 된 패킷이 있는 경우, loss 된 패킷만 다시 보냄
- 수신자는 패킷을 수신하면 각 패킷에 대한 ACK을 보냄
- 송신자는 unACKed 패킷에 대해 각각 타이머를 가짐
Go-back-N
- K-bit의 시퀀스가 패킷 헤더에 존재
- 크기 N의 윈도우 → 패킷 N개를 관리함
- 보낸 패킷의 수가 window 사이즈를 넘어서면 패킷을 더 못보냄 base ~ base + window 사이즈 만큼의 시퀀스 가진 패킷 전송가능
- ACK(n) : n까지 ACK 완료 : culmulative ACK : 받은 패킷의 마지막 시퀀스 번호로 ACK을 보냄
- timer : 가장 오래된 unACKed
- timeout(n) : 타임아웃 시, n번 부터 마지막으로 보낸 패킷까지 (nextseq - 1) 재전송
N = 4 일 때,
센더가 순서대로 0, 1, 2, 3 번 패킷 까지 전송 한다. 리시버가 0번 패킷을 받으면 0번에 대한 ACK을 답변하고 1번을 받으면 1번에 대한 ACK을 전송한다. 그러다가 2번 패킷이 loss 되었고 그 다음 패킷인 3번 패킷이 리시버에 도착하였다면 리시버는 마지막으로 ACK을 전송했던 1번에 대한 ACK을 전송한다.
0번에 대한 ACK을 받고 센더는 base의 값을 0에서 1로 조정하고, 4번 패킷을 전송하고, 1번에 대한 ACK을 받은 센더는 base를 1에서 2로 조정한 뒤 패킷 5번을 전송한다. 그 다음으로 2번 패킷의 ACK이 아니라 2번 패킷은 loss 되고 3번 패킷을 수신한 상태이기 때문에 1번 패킷의 ACK을 수신하게 된다. 1번 ACK은 이미 수신했기 때문에, base 값은 조정하지 않고, 타이머의 타임아웃이 발생하면 2번 패킷 부터 N개를 재전송한다.
Selective Repeat
- 리시버는 수신한 각각의 패킷에 대해 ACK 응답을 보냄 → 리시버에도 (ACK)버퍼의 관리가 필요하다
- 센더는 ACK이 오지 않은 패킷에 대해서만 재전송을 한다
- 센더 윈도우 = N 개 까지 관리 timeout(n) : n번째 패킷을 재전송하고 타이머를 재 실행한다. ACK(n) : n번째 패킷 수신했다고 기록, 만약 가장 작은 unACKed 인데 ACK 왔다면, 다음 unACKed 패킷 호로 base 슬라이딩
- 리시버 pkt n in [rcvbase, rcvbase + N - 1] : ACK(n) 보냈음을 기록
- 순서에 안맞는 시퀀스의 패킷이 수신되었다면, 버퍼에 저장
- 순서에 맞게 deliver 함 pkt n in [rcvbase - N, rcvbase -1] : ACK(n) → base 이전의 패킷들은 이미 수신한 패킷들 → ACK 보내서 재전송안하도록함 다른 경우 - 무시한다.
N = 4 이고, 시퀀스 범위가 0~7까지 있고, 2번 패킷을 loss 하는 상황에서
Selective Repeat의 경우
센서는 0, 1, 2, 3 번 패킷을 순서대로 전송한다. 리시버가 0번의 패킷을 받고 0번에 대한 ACK을 전송하고 rcv_base를 1로 조정한다. 1번 패킷을 받고 1번에 대한 ACK을 전송한 뒤, rcv_base를 2로 조정한다. 2번 패킷은 loss 되어 리시버는 받지 못하고, 3번 패킷을 받았을 때 3번에 대한 ACK을 버퍼에 기록하지만, 2번 패킷에 대한 ACK을 보내지 못했기 때문에 rcv_base는 조절하지 못한다.
센더가 0번 패킷에 대한 ACK을 받으면 base를 0에서 1로 슬라이딩 하고, 다음 패킷인 4번 패킷을 전송하고, 1번 패킷에 대한 ACK을 받으면 base를 1에서 2로 슬라이딩 한 뒤 패킷 5를 전송한다. 패킷3에 대한 ACK을 받았을 땐 버퍼에는 ACK을 기록하지만, 패킷 2에 대한 ACK을 받지 못했기 때문에 윈도우를 슬라이딩하지 않는다. 패킷 2에 대한 타임아웃이 발생하면 센더는 패킷 2를 재전송한다.
패킷 2를 수신한 리시버는 2번에 대한 ACK 을 보내고, 버퍼에 ACK을 기록하고 base를 ACK을 보내지않은 패킷 중 가장 작은 번호로 조절한다. 센더도 2번에 대한 ACK을 받았다면 base를 마지막으로 ACK을 수신한 패킷번호 + 1로 슬라이딩 한다.
- 딜레마 : 시퀀스의 범위가 0, 1, 2, 3 이고, 윈도우 사이즈가 3일 때, 만약 0, 1, 2번 패킷은 전송에 성공하고 ACK도 문제없이 전송되었을 때, 패킷 3번이 loss 된다면 리시버의 윈도우는 3, 0, 1 번 패킷을 기다리고 있기 때문에, 3번 패킷을 재전송해도 문제가 없다. 그러나 0, 1, 2번 패킷을 수신한 리시버가 0,1,2에 대해 ACK을 전송했는데 ACK이 loss 된다면 수신 측은 0, 1, 2 패킷을 수신하고 3, 0, 1 패킷을 기다리는 상태일 것이다. 그러나 송신측은 ACK을 받지 못했기 때문에 0, 1, 2번의 패킷을 재전송 할 텐데, 이때 송신되는 0, 1번 패킷과 수신측에서 기다리는 0,1 번 패킷은 다른 패킷이다. 따라서 수신측에서 새로운 0, 1 번 패킷이라고 인식하고 수신하기 때문에 수신된 패킷에 오류가 발생한다
- 해결 방법 : 시퀀스의 범위와 윈도우 사이즈의 크기를 적절하게 설정해야한다. 시퀀스의 크기가 n bit일 때 (2^n개) → 윈도우의 크기는 2^n/2 보다 작게 설정해야한다.
Summary
- checksum : 데이터 의 비트 에러를 감지
- timer : timeout과 loss에 대비하여 재전송을 하기 위해 타이머 실행
- 시퀀스 넘버 : 패킷의 순서를 유지하기 위해 시퀀스 넘버 관리
- Acknowledgement : 수신측에서 송신측에게 수신을 알리기 위함
- Negative Acknowledgement : 수신하지 못했음을 알림 → 잘 사용하지 않는다
- Window, pipelining : 신뢰성있는 통신의 성능 향상을 위해 한번에 N개 씩 보내는 전략
Connection-Oriented transport : TCP
- 연결지향 프로토콜
- 데이터 전송 전 핸드셰이킹 과정을 통해 송신과 수신측 사이의 연결 확립이 필요
- 전이중 통신
- 같은 연결에서 양방향으로 통신 가능함
- MSS : Maximum Segment Size
- 흐름 제어 : 수신측이 수신할 수 있는 상황인지 체크 후 데이터 전송
- point - to - point : 1:1 통신
- reliable, in-order stream : 신뢰성있는, 순서가 있는 전송
- pipelined : 한번에 패킷을 여러개 보내서 효율성 향상
Header
- Sender Port / Destination Port
- SequenceNumber
- Acknowledgement Number
- Flags
- ReceiveWindow ,,,
Sequence, ACKs
- 보내야할 데이터 크기 = 500,000 바이트, MSS = 1000byte면,
- 단편화 필요 = 500,000 / 1000 = 5000개 의 세그먼트
- seq = 0 → seq = 1000 → seq → 2000 → … → seq = 499,000
- MSS = 세그먼트의 크기 (Payload 크기) MTU = 패킷이 전송할 수 있는 최대 크기 IP 헤더 + TCP 헤더 + payload (이더넷 기준 1500 byte)
- A→B 로 전송하는데 0 ~ 535 byte 가 오고 다음 세그먼트의 시퀀스넘버가 900 -1000이야 → 536 ~ 899 번째 bit 가 도착하지 않음 → B는 536을 계속 기다려~~~~ → TCP 는 Cumulative ACK 방식을 사용한다.
- 첫번째 세그먼트 시퀀스 넘버 = 초기 시퀀스 넘버
- 두번째 세그먼트 시퀀스 넘버 = 첫번째 세그먼트 시퀀스 넘버 + 세그먼트 크기
- Ack number = 다음에 와야할 세그먼트의 넘버, Cumulative ACK → 만약에 seq = 1000 으로 1000 byte 짜리 데이터가 왔어 → 그러면 ACKnum = 1000 + 1000
- 다음으로 보낼 세그먼트의 Seq num = 2000
Telnet Example
A→ B : ‘c’ 전송 & echo
- A → B : seq = 42, ack = 79, data = ‘c’
- B → A : seq = 79, ack = 43, data = ‘c’
- A → B : seq = 43, ack =80, data = ‘c’
TCP RTT (Round Trim Time)
- TCP Timeout 값 어떻게 설정 : RTT 보단 길어야함, 그러나 RTT 넘나 다향
- timeout 짧으면 : 타임아웃이 금방 되어서 불필요한 재전송이 많아짐 너무 길면 : loss 시에 대응이 늦어짐
- RTT어케 측정
- SampleRTT : RTT 샘플링 : 넘나 다양 → 부드러워질 필요있음
- EstimateRTT
-
- safety Margin = DevRTT
TCP Reliable Data Transfer
- 비신뢰성 프로토콜인 IP 위에서 신뢰성있는 서비스를 제공함 → 파이프라인 세그먼트 → culmulative ACKS → 한개의 재전송 timer
- 재전송 발생
- timeout 시
- 중복 ACK 발생하는 경우
Fast Retransmit
- timeout 까지 기다리지 않고, 중복 ACK 으로 패킷 loss 를 감지할 수 있음
- 만약, 센더가 중복 ACK을 3개 이상 받는다면 → 가장 작은 unACKed 세그먼트 재전송 → 타임아웃까지 기다리지 않아도 되기 때문에 효율적
- 하이브리드 전략! Go-back-N처럼 Cumulative ACK을 사용하고, (: 무조건 받은 패킷에 대한 ACK을 전송) Selective Repeat 처럼 전송안된 패킷만 재전송함
Flow Control
- 리시버의 버퍼를 확인해 리시버가 받을 수 있는 상황에만 데이터 전송함 → 헤더에 Receive Window
- 큰 파일을 보내는 상황
- 리시버는 이 연결을 위해 버퍼를 할당 = RcvBuffer
- 리시버는 TCP 헤더를 통해 rwnd Value(=남은 버퍼의 크기)를 센더에게 알림
- RcvBuffer 는 소켓 옵션으로 설정, 보통 4096 바이트
- 센더는 rwnd 값을 보고 전송하는 데이터의 양을 조절함
Connection Management
- 3-way Handshaking : 데이터를 전송하기 전에 연결을 확립하기 위한 과정
- C → S : SYN = 1, seq = client_isn
- S → C : SYN = 1, seq = server_isn, ack = client_isn + 1
- C → S : SYN = 0 (동기화 종료), seq = client_isn + 1, ack = server_isn + 1
- 연결 종료
- C → S : FIN = 1
- S → C : ACK = 1
- S → C : FIN = 1
- C → S : ACK = 1
- 둘다 FIN을 보내고 ACK을 보내야 연결이 종료됨
- SYN Flood Attack
- Connection을 이용한 공격
- 공격자는 봇넷을 이용하여 서버에 수많은 SYN 요청을 보냄 → 서버에서 SYN에 대한 응답을 해주면, 공격자는 SYN 종료를 하지 않음 → 서버는 응답을 계속 기다려서 자원이 소모됨 → 정상적인 사용자들의 요청을 받지 못함
Congestion Control
- 많은 소스들이 많은 데이터들을 네트워크로 보냄 → 네트워크도 혼잡해짐
- 흐름 제어와 다름
- 흐름제어 : 리시버의 상태를 보고 전송량 조절 / 혼잡제어 : 네트워크의 혼잡정도를 보고 전송량 조절
- 네트워크 혼잡으로 인해
- lost packet : 라우터의 버퍼가 오버플로 되면서 패킷 drop
- long delay : 라우터 버퍼에서 큐잉을 기다리면서 delay 생길 수 있음 ⇒ 두가지가 발생하면 네트워크가 혼잡하다고 판단하고 송신량을 제어함 → 따라서 loss = 중복ACK, delay = timeout에 따라 제어
- 시나리오
- 이상적인 상황
- 2개의 센더, 2개의 리시버, 라우터 하나-버퍼 무한
- 링크 대역폭 : R
- 재전송 없는 경우 → 각 통신은 최대 R/2 의 속도 → 송신측에서 보내는 데이터의 양을 아무리 늘려도 링크의 대역폭 크기 때문에 라우터에서 큐잉 딜레이가 발생하게 됨 (속도는 계속 R/2로 유지되지만, 큐잉 딜레이는 무제한으로 늘어남) → 이상적인 상황에서도 혼잡 발생함
- 시나리오 2
- 라우터 1개, 유한한 크기의 버퍼
- 센더는 타임아웃 패킷으로 인해 재전송 할 수 잇음
- 따라서 애플리케이션에서 전송하는 데이터 in = out 이지만, 전송 계층에서 재전송하기 때문에 in’ ≥ in → 라우터가 유한하기 때문에 라우터가 꽉차면 오버플로우가 생겨 드롭되는 패킷이 생김 → 드롭되는 패킷은 재전송해야함 → 재전송으로 소모되는 대역폭이 있기 때문에 최대 전송속도는 R/2 보다 작다
- 중복패킷도 생김 → 중복 패킷 + 재전송 패킷 → 송신은 R/2만큼 해도 수신측은 R/4만큼 수신함
- 시나리오 3
- 송신 4명
- 멀티홉 경로
- 타임아웃, 재전송 발생 → 한 라우터에 대해 원홉인 호스트가 투홉인 호스트 보다 더 많이 사용하게 됨 → 투홉인 호스트의 패킷은 드롭될 가능성이 높음 → 투홉인 호스트가 해당 라우터가 꽉찬지 모르고 데이터 전송함으로써 자기한텐 첫번째 라우터의 버퍼를 소모해서 또다른 호스트도 못쓰게 함 → 두번째 라우터에서 드롭될 패킷을 위해 네트워크 자원을 소모함 → 원홉의 in’가 늘어나면 투홉의 out도 어느정도 늘어나다가 어느 순간부터 뚝 떨어짐 ( 처음엔 in’과 상관없이 전송되다가, in’이 늘어나면 out의 전송량이 줄어들음)
- 혼잡 cost
- 재전송으로 인해 input이 많아짐
- 불필요한 재전송 → 링크는 똑같은 패킷 전송을 위해 낭비
- 버려질 패킷을 위해 네트워크의 대역폭을 소모
- Approachs
- End-to-End Congestion Control : 각각의 호스트가 네트워크의 혼잡도를 계산해서 데이터 전송량을 조절 → 주로 사용 (혼잡도 아는 법 : 중복 ACK → loss / timeout → 혼잡으로 딜레이 발생 - 어떤 장앤지 예측 불가 ㅠ )
- Network-assisted congestion control : 네트워크 안에 라우터가 자신의 버퍼를 모니터링하고 호스트에 알려주는 기능이 구현됨 (복잡도 계산) → 네트워크 구성/라우터를 바꿔야하는 문제라 적용하기 어려움
- 센더가 전송률을 조절하자 (Window Size 조절)
- cwnd = Congestion Window
- addictive increase : cwnd 를 매 RTT 마다 1 MSS 씩 증가
- multiplicative decrease : loss 발생 시, cwnd를 반씩 줄임
- 혼잡제어는 센더가 Congestion Window를 통해 보내는 양을 조절함
- rwnd 와 cwnd 값 중 작은 값을 보고 보내는 데이터 양 결정
- cwnd 값에 따라 전송 한계를 정함 : cwnd는 동적이다 → loss 발생 여부에 따라 값이 변함
- TCP 전송률은 거의 cwnd / RTT byte/sec (rwnd 가 매우 크다는 가정)
- Slow Start : 연결이 시작되고, cwnd를 지수적으로 첫 loss 발생시까지 증가 시킴 초기 cwnd = 1 → 매 RTT 마다 더블링 (2배) 1 → 2 → 4→ 8→ … → 초기 값은 작지만 빠르게 증가한다
- Congestion Avoidance : 마지막으로 congestion avoidance가 발생했었을 때의 cwnd 의 half에 도달하면 congestion avoidance 시작ssthresh 이후 부터는 congestion avoidance 수행 → 1 MSS 씩 만 증가 시킴 = 전송량을 천천히 증가 시켜 혼잡을 피함 ⇒ (TCP Tahoe의 경우) 그러다 loss 발생하면 cwnd를 1로 줄여 slow start 수행 & ssthresh 값 마지막 congestion avoidance 지점의 반 값으로 조정
- 마지막으로 congestion avoidance가 발생했었을 때의 cwnd 의 half = ssthresh
- Fast Recovery :
매 중복 ACK발생시마다 cwnd 3씩 증가→ 추천되는 방식, 강요는 아님 (TCP Reno) → loss 발생 시, ssthresh + 3 부터 시작해서 1 MSS 씩 증가 시킴 → 네트워크 성능을 위한 방식 : 시작점이 높아서 전송률 회복이 빠름
- TCP Fairness : K 개의 TCP 세션이 있을 때, 각 연결들은 각각 혼잡제어를 하면서 전송량을 제어하기 때문에 각각은 평균 전송률이 R/K으로 공정하게 데이터가 전송된다. (링크 길이가 같고, 스케쥴링이 없는 경우)
- 전송량을 증가시키가다 혼잡 발생 시 조금 보내는등 혼잡제어를 하기 때문에 처리량이 공정해짐
- Explicit Congestion Notification (ECN)
- Network-assisted Congestion Control
- IP 헤더의 2bit에 라우터의 혼잡을 기록
- 혼잡 표시가 수신 측에 전달됨
- 혼잡표시가 있는 패킷을 받은 수신 측은 송신측에 ACK을 보낼때 ECN 에 1을 표시해서, 송신측에 네트워크가 혼잡함을 알림 → 네트워크 인프라가 ECN bit를 지원해야하기 때문에 범용적으로 사용하기 어렵다
- TCP Tahoe
- 패킷 로스 발생시 slow start를 하게 되어 cwnd를 1로 줄임
- TCP Reno
- 패킷 로스 시
- 중복 ACK 3개 수신 → fast recovery 통해 cwnd = ssthresh + 3으로 조정
- timeout → slow start를 통해 cwnd = 1로 줄임
'네트워크' 카테고리의 다른 글
[API] API 종류 - SOAP vs REST vs GraphQL (0) | 2023.03.14 |
---|---|
[네트워크] OSI 7_Application Layer/HTTP 버전별 특징 (0) | 2023.02.19 |
[네트워크] OSI 7_Application Layer/HTTP 개요 (0) | 2023.02.18 |
[네트워크] Cisco Packet Tracer 실습해보기 (0) | 2022.11.21 |
[네트워크] Cisco Packet Tracer 시작하기 (0) | 2022.11.21 |