티스토리 뷰

네트워킹

TCP 의 Flow control

4whomtbts 2020. 6. 19. 05:10

TCP 는 flow control service 를 제공한다.

Flow control service의 지상목표는 sender 가 receiver 의 buffer를 overflow 시키지 않도록 해주는 것이다. 

그래서, Flow control service 를 speed matching service 라고 말 할 수 있다. 

sender 에서 produce 하는 속도와 receiver 가 consume 하는 속도를 매칭시켜서 receiver 가 overflow 되거나 

지나치게 위축되어서 둘 사이의 Link capacity 를 충분히 활용하지 못 하는 상황을 방지해서 최적의 균형점을

찾아주는 service 인 것이다.

 

TCP는 sender 측에서 receive window 라는 변수를 유지함으로써 근본적으로 작동할 수 있게 된다.

이 receive window 변수의 목적은, receiver 가 버퍼에 얼마만큼의 여유공간이 있는지 알려주는 변수이다.

 

Host A 를 보내는 측, Host B 를 받는 측 이라고 하면 

Host B는 A에게 보내는 세그먼트마다 자신의 rwnd(receive window)를 갱신해서 알려준다. 

그러면 Host A는 LastByteSent - LastByteAcked <= rwnd 인 범위 내에서 데이터를 보냄으로 써, 

connection 동안에 B를 overflow 시키지 않는것을 보장한다.

 

만약에 Host B의 receive buffer 가 가득차서, 즉 rwnd = 0이 되어서 A에게 이 사실을 알리고나서, B 또한 A에게 보낼 데이터가 없다고 한다면

어떻게 상황이 진행될까? 

B는 일정 시간이 지난 후에 process에 의해 buffer 가 비워질 것 이다. 하지만 B는 A에게 보낼 데이터가 없기 때문에 

A는 B가 available 하다는 사실을 계속 모를 것이 분명하다. 따라서 A는 block 된 상태로 아무 데이터도 보내지 못하고 있을 것 이다.

이러한 상황을 해결하기 위해 TCP 명세에서는, B의 receive window size가 0 일 때, A로 하여금 지속적으로 

1 byte 의 data byte를 가진 segment 를 보내도록 하고 있다. 따라서 지속적으로 이 자그마한 세그먼트를 보내보다가

B의 buffer 비워져서 A가 데이터를 보낼 수 있게 된다면, A는 그제서야 원하는 데이터를 보낼 수 있게 된다.

 

 ○ TCP Connectin 관리

1.

클라이언트의 TCP 는 서버 TCP에 특별한 TCP segment 를 보낸다. 이 특별한 TCP segment 에는 아무런 application layer의 데이터도 담겨있지 않다.

다만, segment header의 flag bit가 set 되어있다.

즉 위의 빨간색으로 강조한 SYN bit가 1로 set이 되는 것 이다. SYN은 Synchronize 의 약자이다.

클라이언트는 랜덤하게 intial sequece number를 선택한다. 여기서 왜 0부터 시작하지 않고 initial sequence number를

선택하는지가 의문이었었는데, 그 이유는 Security 때문이다. 만약에 SYN 이 0부터 시작하는 것으로 고정되어 있다면

Connectin spoofing, Connection resetting, data injection 같은 공격에 취약해진다.

(https://www.quora.com/Why-in-a-TCP-sequence-is-a-number-taken-as-a-random-number-and-what-is-the-actual-number-at-the-start)

항상 악용하는 사람들은 있기 때문에 어쩔 수 없지만 , 보안 때문에 소모되는 리소스(Network bandwidth, CPU clerk) 은 정말 아깝다. 

ADSL, Stack canary 나 암호화 하는 비용(AES, RSA..), CORS

본론으로 돌아가서, random 하게 generate 된 sequence number를 sequence number field 에 넣고 IP datagram으로

만들어서 서버로 보낸다.

2.

TCP SYN을 포함한 segment 가 서버에 도착하면, 서버에서는 TCP segment 를 추출해서 해당 connectioni에 

TCP buffer와 variable 들을 할당하고, connection-granted segment를 클라이언트에 보내주게 된다.

당연히, connection-granted segment 또한 application layer의 data를 포함하지 않는다.

대신에 중요한 3가지 정보를 포함하는데

ㄱ. 1로 설정 된 SYN bit

ㄴ. 클라이언트에서 보낸 sequence number(client_isn)에 1이 더해진 값으로 세팅 된 acknowledgement field

ㄷ. 서버만의 고유한 initial sequence number(server_isn) 그리고 이것을 sequence number field에 넣는다

이 connection-granted segment 를 SYNACK segment 라고도 부른다.

여기까지 되면, 서버와 클라이언트를 의인화 시켜보면 

클라이언트: 너랑 통신하고 싶어, client_isn 은 76 이니깐 통신할 생각이 있으면 답장 줘

서버: 네가 보낸 SYN packet 은 잘 받았어, 거기에 써있는 client_isn 인 76도 잘 받았어, 좋아 너랑 통신할께

       내 server_isn 은 47이야, 그리고 네가 보낸 요청을 잘 받았다는 증거로 네가 보낸 client_isn 에 1을 더해서

       보내줄테니깐 확인해 

3. 

클라이언트가 SYNACK segment 를 받으면 클라이언트도 또한 buffer 와 variable을 할당합니다. 그리고나서 

서버가 SYNACK segment에 껴넣은 server_isn 에 1을 더합니다. 그리고 SYN bit를 0로 설정합니다.

이제, 클라이언트는 자기가 보내고자 하는 데이터를 실어서 서버에 보낼 수 있습니다.

 

위의 세 번의 과정이 그 유명한 TCP 의 Three-way Handshake입니다. 

 

 ○ TCP Connectin 의 종료는 어떻게 할까?

connection 의 시작이 있으면 끝도 있는것이 당연하다. TCP 는 어떻게 연결을 종료할까?

빨간색으로 강조해놓은 필드의 이름을 보아하건데, FINISH 의 약자일테니, 용도가 뻔히보인다.

클라이언트에서 이 FIN 필드를 1로 세팅해서 서버에 보내면, 서버는 이것을 감지하고 클라이언트에 연결을 종료한다는

acknowledgement segment를 보내준다. 그리고나서 서버는 자신만의 shutdown segment를 보내주는데 이 segment 

또한 FIN 필드가 1로 세팅되어 있다.

클라이언트는 서버가 보낸 shutdown segment를 읽어보고 연결을 종료가 무사히 되었음을 확인한다.

 

 ○ TCP Connectin 의 생애주기

이처럼 TCP connection도 생애주기가 존재한다. 

client에서 TCP 는 처음에 CLOSED 상태로 시작한다. 클라이언트측에서 SYN을 서버에 보내면 클라이언트의 TCP는 

SYN_SENT 상태가 된다. 그리고 서버로부터 연결이 성사되었다는 acknowledge를 받게되면, ESTABLISHED 상태로 바뀐다.

이 상태에서 클라이언트가 연결을 종료하고자 한다면, FIN_WAIT_1 상태로 바뀌게 되며, 서버에서 연결종료에 대한 acknowledge를 받게되면 FIN_WAIT_2로 바뀐다.

그리고나서 서버에서 FIN 필드가 1로 세팅된 Shutdown segment를 받을 때 까지 기다린다.

이 Shutdown segment를 받게되면 TIME_WAIT 상태로 바뀌게 된다. TIME_WAIT 을 얼마나 유지할 것인가는 구현에 따라 다르지만

일반적으로 30초, 1분 혹은 2분정도 이다.기다린 후에, CONNECTION 은 정식으로 닫히게 되며 connection을 위해

할당해두었던 모든 자원들을 할당 해제한다

그런데, TIME_WAIT 의 용처를 아무리 상상해봐도 떠올려지지가 않았다. 그래서 검색을 해 보았는데 

엄청 좋은 글을 찾을 수 있었다. (http://docs.likejazz.com/time-wait/) 꼭 TIME_WAIT 뿐만 아니라 이 글에 대한 심화적인

내용도 많이 포함되어 있으니, 꼭 읽어보길 권한다.

'네트워킹' 카테고리의 다른 글

Hot potato Routing  (0) 2020.06.22
Network Layer  (0) 2020.06.21
TCP Congestion control  (1) 2020.06.19
Transport Layer  (0) 2020.05.26
댓글