본문 바로가기
네트워크

[네트워크] Chap 3.6 - TCP flow control & Connection management

by 개발 고양이 2024. 11. 24.

TCP flow control


- application이 receive buffer에서 데이터를 읽어가는 속도(A)와 sending TCP가 보내는 속도 (B) 가 다름
- B가 A 보다 지나치게 크면, receive buffer 가 아무리 커도 overflow 발생할 수 있음.

- 즉, 들어오는 속도가 너무 크면 버퍼를 아무리 크게 잡아도 소용 없음.

   => 핵심은 버퍼의 크기가 아님. 들어오고 나가는 률의 차이가 관건!


TCP flow control이란?

receiver가 sender를 control하는것을 말한다.

buffer의 잔여량을 알려줘서 sender host의 sending rate를 control

=> receiver buffer의 overflow를 방지하기 위한 목적이다!

 

receiver buffer의 크기는 connection set-up을 해서 socket을 생성할 때 직접 자기들끼리 주고받는다.

sender는 free buffer space의 크기(=rwnd)만큼 데이터를 추가로 전송이 가능한데,

unacked data의 양, 즉 전송 중인 데이터의 양이 rwnd보다 크지 않도록 제한한다.

 

 

How does TCP sender resume sending when it received ACK with rwnd=0 from TCP receiver?

만약 rwnd가 0이라면?
=> sending TCP가 제어 segment를 보내서 receiving TCP가 (변경된 rwnd > 0 값을 포함한) ACK 세그먼트를 보내도록 함.


Agreeing to establish a connection

2-way handshake

사람들끼리 대화할때, "나랑 얘기하자" ↔ "좋아" 와 같이 2번의 의사 전달로 연결이 된다.

 

client가 연결을 원한다고 server에게 데이터를 보내고,

server가 연결을 수락했다고 client에게 데이터를 보낸다.

 

이와 같이 2번의 의사 전달로 connection을 맺는 것을 2-way handshaking 이라고 한다!

 

 

위 그림은 2-way handshake로 connection 후 data를 전송하는 이상적인 시나리오이다.

 

① client가 connection 요청

② server가 connection 수락 의사 전달

③ client가 data 전송

④ server가 data를 잘 받았다는 ACK 전송

=> 즉, client도 server가 안다는 사실을 확인하고, server도 client가 내 의사를 안다는 사실을 확인한 다음에 establish하면 아무 문제가 없다

 


2-way handshake의 2가지 문제상황 시나리오를 살펴보자!

(왼쪽이 client, 오른쪽이 server이다)

문제상황1

server의 connection accept 응답이 늦게 도착하는 바람에, client는 req_conn을 재전송한다.

 

재전송 후, 아까 server가 보낸 느린 응답이 뒤늦게 도착한다.

client는 이 응답이 자신이 처음에 보낸 req에 대한 응답인지, 재전송한 req에 대한 응답인지 구별할 수 없다.

=> 어쨌든 client는 accept 응답을 받았으므로 연결을 설정한다.

 

시간이 지나 연결이 종료된다.

 

연결 종료 후, client가 재전송한 req가 server에 도착한다.

server는 accept 응답을 보낸다.

 

client는 connection request를 한적도 없는데 갑자기 accept응답을 받은 셈이다.

이렇게 되면, server는 있지도 않은 client를 위해 socket을 열고 buffer를 할당해야 한다. half open connection이 생긴다!

 


문제상황2

시작은 앞 상황과 똑같다.

server의 connection accept 응답이 늦게 도착하는 바람에, client는 req_conn을 재전송한다.

 

재전송 후, 아까 server가 보낸 느린 응답이 뒤늦게 도착한다.

client는 이 응답이 최초의 req에 대한건지, 재전송한 req에 대한건지 구별이 불가능하다.

=> 어찌됐든 client는 accept 응답을 받긴 받았으므로, 연결을 설정한다. (ESTAB)

 

연결 설정 후 client가 server에게 data(x+1)을 보낸다

근데 server가 데이터를 잘 받았다는 ack이 loss되었다고 치자

client입장에서는 server로부터 ack이 안왔으므로 data(x+1)을 재전송한다.

 

그 후 connection이 종료된다

종료 이후 재전송한 req_conn와 뒤늦게 서버에 도착하여 server는 ESTAB한다.

재전송한 data도 뒤늦게 서버에 도착한다.

(server는 있지도 않은 client를 위해 버퍼도 할당하고 cpu도 돌아가고,, 이런 일이 생긴다)

 

 

 

=> 그래서 결론은?

: 3-way handshaking을 해야한다!


TCP 3-way handshake

  1. SYNbit=1, Seq=x, (ACKbit=0, ACKnum=쓰레기값)
    client TCP는 initial seq num(ISN)를 pick (여기선 x)
    우리 point-to-point로 socket을 열자 라는 의미로 SYNbit를 1로 설정해서 보낸다.
    이 과정을 거치면 client state는 SYNSENT 상태로 바뀐다.

  2. SYNbit=1, Seq=y, ACKbit=1, ACKnum=x+1
    server도 처음 받으면 ok 하면서 ISN=y로 설정
    나도 연결을 설정하겠다는 의미로 SYNbit를 서버도 활성화
    (SYNbit와 ACKbit를 합쳐서 SYNACK Segment라고도 한다)
    응답을 보낸 후 server는 SYN RCVD 상태로 바뀐다.
    이 응답을 client가 받으면 server가 현재 응답을 받을 수 있는 상태라는걸 확인했으므로 client는 ESTAB 상태가 된다.

  3. SYNbit=0, Seq=x+1, ACKbit=1, ACKnum=y+1
    client는 server에게 응답을 잘 받았다는 의미로, ACKnum을 y+1로 설정하여 보낸다.
    대부분 이때 데이터도 같이가는데, ACK과 Data가 같이가는걸 piggybacked라고 한다!

 

Initial Sequence Number (ISN)을 random하게 설정하는 이유?

=> 이전에 맺었던 connection에서 잔여로 남아있는 데이터가 또 들어왔을때 착각하지 않기 위해서!


TCP: closing a connection

TCP는 full duplex, 즉 동시에 보내면서 받는다

따라서 client의 sending buffer & receiving buffer, 그리고 server의 sending buffer & receiving buffer을 각각 닫아줘야한다.

 

1. FINbit=1, seq=x

client가 FINbit를 1로 설정하여 보내면, client의 sending buffer가 종료된다.

client는 더이상 데이터를 보낼 수 없는 상태가 된다. (하지만 아직 receive는 가능)

 

2. ACKbit=1, ACKnum=x+1

server가 FINbit=1을 받으면, server는 client에게 ACK을 보낸다. 아직 server는 data를 보낼 수 있는 상황이다.

 

3. FINbit=1, seq=y

server가 FINbit를 1로 설정하여 client에게 보내면, 이제 양방향 통신이 다 끊기게 된다.

 

4. ACKbit=1, ACKnum=y+1;

마지막으로, client는 server의 FINbit를 수신한 후 똑같이 ACK을 보내서 알려준다.

 

서버의 sending buffer가 닫히면, 양방향이 다 끊기게 된다. 하지만 이때 ACK이 loss로 인한 retransmission을 대비하여 (2*max segment lifetime) (보통 2분 정도)만큼 기다린다.
클라이언트의 응답 없을 시 서버는 maximum number of retry 후 종료

 

 

 

TCP connection management :
Why does TCP need 3-way handshaking for connecting two end systems?

=> 중간에 connect(), accept() 메세지가 경유하는 네트워크가 unreliable and best-effort 서비스를 하는 IP 프로토콜로 서비스 되므로 or 패킷스위칭으로 동작하는 unreliable Internet 을 거쳐가기 때문
=> 서버는 자신이 보낸 accept() 를 client가 잘 받았다는 확인을 한 다음에 해당 client를 위한 resource (buffer, ISN, .. etc)를 OS로 부터 할당 받아야 한다.

=> Need to sure that B knows A is ready to talk B