Transport Layer(3) - TCP

June Lee·2021년 5월 18일
0

네트워크

목록 보기
6/28

TCP

한 쌍의 프로세스 간의 통신(엄격하게 말하면 소켓 한 쌍끼리의 통신) point-to-point
유실되지 않으면서 순서대로 가지고 감
pipelined -> window 크기만큼은 ACK랑 상관없이 쏟아부음 -> 재전송도 window 크기 단위로 -> 그래서 receiver 쪽에도 버퍼를 둬서 selective하게 재전송할 수 있게 했음
양방향 통신 (서버, 클라이언트에 모두 sender buffer, receiver buffer가 있음)
연결지향
흐름제어 -> receiver의 능력에 맞는 양만큼 보내줌 -> receiver에서 헤더에 available space 정보를 담아서 보내줌 -> 보내는 속도(bps) = 보내는 양/sec 니까 보내는 양을 늘리면 속도가 빨라짐 -> available space가 0이라면? sender가 주기적으로 데이터 없이 segment를 보냄. 그래야 receive에서 공간이 비었을 때 거기에 대한 ACK를 보낼 수 있음.
혼잡제어 -> network 상황이 받아드릴 수 있을만큼 보내줌

계층별 정보
Application Layer : HTTP : Message(header + data)
Transport Layer : TCP/UDP : Segment(header + data)
Network Layer : IP : Packet(header + data)
Link Layer : Frame(header + data)

윗 계층의 데이터가 아랫 계층의 data 부분에 쏙 담김
여기서 중요한 부분은 각 계층에서 붙이는 header에 담긴 정보

TCP에서 seq#은 메세지를 잘라서 보낼 때 가장 앞 byte#
Go-Back-N에서 ACK10: 10번까지 잘 받았다
TCP에서 ACK10: 9번까지 잘 받았으니 10번을 달라
seq#은 send buffer에서 만드는 거고, receive buffer는 그 seq#을 tracking함

cf.
ACK와 보내고 싶은 데이터의 구분은 header로 함.
ACK를 사실 바로 보내는게 아니라 timer가 있어서 일정 기간을 기다리고, 그 안에 보낼 데이터나 다른 ACK가 있다면 같이 보내고, 없으면 ACK만 보냄 -> 이유? 쏟아져들어오는 데이터에 일일히 ACK 보내면 손해. cumulative ACK

ACK에 대한 timeout

Round Trip Time(RTT)를 기준으로 timeout을 잡으면 되지 않을까?
그런데 RTT는 모든 세그먼트마다 조금씩 다름(경로(지나는 라우터)도 다르고, Queuing delay는 네트워크 상황에 따라 예측 불가)
지금까지의 RTT 값을 통계를 내되, 지금 RTT 값에 약간의 가중치를 줘서 지금 네트워크 상황을 반영 -> 어느정도 고정된 값을 사용함 (거기에 마진을 넉넉하게 더해줌)

TCP의 Reliable Data Transfer

pipeline 방식
cumulative ACK -> ACK 10이면 9번까지 잘 받았고 10번 달라 -> culmulative ACK는 일단 특정 번호까지는 잘 받았다는 것을 확실히 알 수 있다는 것이 장점
timer 하나 사용 -> Go-Back-N과 동일. 다른 점은 윈도우 전체 재전송 x. 해당 세그먼트만 재전송.

예를 들어 10번 seg가 없다고 한다면,
ACK 1, 2, 3,... 9까지 간 후 10이 계속 반복됨 (이 상황에서도 timeout 전까지 11번 이후 seg를 계속 받아서 receive buffer에 차례대로 담아두기는 함)
=> 그래서 TCP에서는 timeout되기 전에 특정 ACK가 4번 이상 반복되면(3 duplicate ACKs) timeout 되기 전에 미리 재전송하도록 권고함 = Fast Retransmit (필수는 아님. 타이머만 있어도 재전송해줄 수 있기 때문에.)

3 duplicate ACKs로 packet5 재전송한 후 receiver는 8번까지 받았으니 ACK9를 보내고, 그럼 이제 sender는 9번부터 다시 보냄

TCP 3-way Handshake

data에는 아무것도 없이, header의 syn에 1과 자기 seq#을 담아서 보냄: TCP Connection하고 싶다는 뜻
syn에 대한 ACK
syn ACK에 대한 ACK

마지막에 나가는 ACK는 데이터(Http Request)를 포함할 수 있음

연결을 끊을 때

FIN을 보내면 거기에 대한 ACK를 보내고 자기도 FIN을 보낸 후 ACK를 받는데,
이때 클라이언트는 FIN을 받고 ACK를 보낸 후 잠시 간 연결을 유지한다. 그 이유는, 예를 들어 마지막 ACK가 유실됐다면 서버에서는 다시 FIN을 보낼텐데 이미 연결이 끊겼다면 계속 timeout되는 상황이 반복되기 때문이다.

혼잡 제어

sender가 데이터를 보내는 양은 receiver와 network 중 더 상태가 안좋은 쪽에 맞춰줘야함. receiver의 상태는 피드백으로 직접적으로 알 수 있음. 그렇다면 network 상태는 어떻게 알 수 있을 까? -> Congestion Control Mechanism

네트워크 상황이 안좋을 경우 TCP는 세그먼트를 잃을 가능성이 많아지고, 재전송으로 네트워크 상황을 더 악화시키는 악순환이 반복됨.
-> 네트워크가 안막히도록 해야함.
-> 서로를 위해 보내는 데이터 양을 줄임.

네트워크 상황 파악 방법
1) End-to-end Congestion Control ✔(TCP는 이걸 이용)
내부상황을 알아서 유추해서 조절. 유추하기 위한 key? ACK가 느리게 오거나 안오는 경우. 이를 통해 유추함. -> 아주 정확하지는 않음

2) Network Assited Congestion Control

TCP Congestion Control 단계
1) 상황을 모르기 때문에 처음에는 조금씩 보냄(slow start) -> 윈도우 사이즈(MSS, Maximum Sigment Size)를 조금씩 증가시킴(addictive increase) -> 윈도우 사이즈가 느린 속도로 증가하는건 아니고 처음에 낮게 시작한다는 뜻.
2) threshold를 넘으면(막히면) 윈도우 사이즈를 절반으로 확 줄이고 다시 시작(multiplicative decrease)

cf.
threshold는 패킷 유실이 발생한 상황에서 윈도우 사이즈 절반으로 세팅함

전송 속도
Congestion Window Size / RTT -> RTT보다는 CongWin 사이즈가 크게 왔다갔다함. 근데 이 크기는 네트워크 상황에 따라 달라짐. 따라서 사용자의 사용량에 따른 네트워크 상황이 전송 속도에 영향을 미침.

패킷 유실을 탐지하는 경우
1) timeout => 유실된 패킷 이후로 윈도우 사이즈만큼의 패킷을 다 안받음
2) 3 dup ACKs => 패킷 하나만 안받음
따라서 네트워크 관점에서 1)과 2)는 매우 다름 -> 다르게 반응
2)로 인한 패킷 유실이라면 절반만큼 줄인 후 linear increase
1)이라면 원래대로 윈도우 사이즈를 처음 수준으로 확 줄이고 다시 slow start

TCP의 Fairness

네트워크라는 공용 자원에서 독립적 congestion control을 하는데, 그렇다면 각 컴퓨터가 자원을 공평하게 사용하는가?

=> 유실이 돼서 1/2씩 줄이는 과정에서 위 지점에서 수렴하게 됨
=> 그렇지만 TCP Connection을 많이 연 컴퓨터가 더 많이 쓰기는 함

profile
📝 dev wiki

0개의 댓글