본문 바로가기

ComputerScience/Network

TCP - 3. flow control, connection management

728x90

1. flow control

통신을 필요로하는 application은 socket을 통해 os와 소통한다.

위 그림은 sender로 부터 패킷을 수신하는 과정을 나타낸다.

tcp socket을 만들면 자동으로 할당되는 receive buffers에 payload(메시지)가 저장된다.

application layer에서 receive()로 버퍼에 저장된 메시지를 읽어오게 된다.

 

그런데 만약 receiver가 저 버퍼에서 메시지를 읽는 속도보다 버퍼에 메시지가 쌓이는 속도가 더 빠르면 버퍼를 꽉 채우고 남은 메시지들은 그냥 버리게 된다.

그래서 receiver는 overflow를 피하도록 sender가 패킷을 보내는 속도를 통제한다. 

이게 flow control이다.

 

flow control 방식은 다음과 같다.

receiver가 sender에게 ack를 보낼 때, 수신할 수 있는 데이터 크기를 알려주는 것이다. TCP header안에 있는 rwnd(receive window)변수를 통해 전달한다.

소켓을 처음 생성하면 할당된 버퍼의 크기는 RcvBuffer이다. 이미 차있는 공간 빼고 수신할 수 있는 크기를 rwnd라고 한다. 그럼 sender는 그 크기를 넘어서 데이터를 보내지 않는다.

2. connection management

sender, receiver는 서로 데이터를 보내기 전에 handshake를 한다고 했다.

sender, receiver가 서로 연결되면 connection에 관련된 state를 관리한다. 

서로 랜덤으로 약속한 seq#, 연결 상태, rcvBuffer 크기 등의 정보를 저장한다.

 

2-way handshake

단순히 연결 요청 - 답장하는 2-way handshake 방식은 실패 가능성이 매우 크다. 

연결 요청에 대한 응답이 늦게 도착하는 바람에 다시 연결 요청을 전송하는 상황을 가정해보자.

이미 한 connection이 만들어졌는데 왼쪽 호스트는 연결을 2번 한 것으로 상황을 인지해버린다.

하지만 두번째 connection에 대해서 정작 연결할 파트너는 없는 이런 상황을 half open connection 이라고 한다.

위의 half open connection 상태에서 데이터 재전송까지 발생하면 위처럼 두번째 connection은 client도 없는데 데이터를 수신하는 꼴이 된다. (ghost data라고 한다)

 

3 way handshake

TCP에서 실제로 connection을 위해 사용하는 방식이다. 2 way 보다 훨씬 안정적임이 증명되었고 연결이 필요한 대부분의 프로토콜이 사용하는 방식이다.

<Client>

(action) connection을 위해 client가 TCP SYN 메시지를 보낸다. 이때 seq#는 무작위로 설정한다(x)

(bit on) 그리고 SYN bit를 on으로 만든다, "이 메시지는 SYN메시지다"라고 헤더에 표시

(state) SYN SENT 상태

->

<Server>

(action) SYN메시지를 수신하고 SYN ACK 메시지를 보낸다. 마찬가지로 seq#는 무작위로 설정한다(y). ACKnum = x+1이다. 

(bit on) SYNbit = 1, ACKbit = 1로 설정하여 SYN ACK 메시지를 나타낸다.

(state) SYN RCVD 상태

->

<Client>

(action) SYN ACK 메시지를 수신하고 SYN ACK를 잘 수신했다는 의미로 ACK를 보낸다. ACKnum = y+1이다. 참고로 client 입장에서는 연결이 완료된 것 이기 때문에 이 ack 패킷에 segment를 담아서 데이터 전송을 시작할 수 있다.

(bit on) ACKbit = 1로 설정하여 그냥 ACK를 나타낸다.

(state) 연결 완료, ESTAB 상태

-> 

<Server>

(action) server가 ack를 수신함

(state) 연결 완료, ESTAB 상태

설명을 상태머신으로 나타면 위와 같다.

 

연결을 했으니 연결을 종료하는 방법도 알아보자.

종료를 원하는 측에서 FIN bit = 1인 segment를 보낸다 -> FIN segment에 대해 FIN bit = 1, ACK bit = 1인 segment를 보낸다 (ACK bit =1 segment를 보낼수도 있다.)

 

<Client>

(action) 종료 요청을 보낸다. 이때부터 전송은 불가능하다. 하지만 수신은 가능하다.(seq#x)

(bit on)  FIN bit = 1 

(state) FIN_WAIT_1

->

<Server>

(action) FIN message 수신, 하지만 아직 보낼게 남아있을 수 있으므로 바로 연결을 닫지 않는다. ACK(x+1)만 보내준다. 

(bit on) ACKbit = 1 or FIN bit = 1, ACK bit = 1

(state) CLOSE_WAIT

->

<Client>

(action) ACK를 수신, 남은 segment가 있으면 마저 수신한다. FIN segment가 올때까지 기다린다.

(state) FIN_WAIT_2

->

->

->

<Server>

(action) 마저 보낼 데이터를 다 보내고 나서 서버도 종료를 원하면 FIN 메시지를 보낸다. (seq#y) 이제부터 데이터를 보낼수 없다.

(bit on) FIN bit = 1

(state) LAST_ACK

->

<Client>

(action) FIN 메시지 수신, ACK(y+1)을 보낸다. 혹시 모를 상황에 대비해 아주 조금만 기다렸다가 연결을 닫는다. 상대방은 내 ACK(y+1)을 수신해야 연결을 종료하기 때문에 혹시 모를 ack 재전송에 대비하여 기다린다. 

(bit on) ACKbit = 1

(state) 일정 시간이 지난 뒤 CLOSED 상태

->

<Server>

(action) ACK(y+1)을 수신, 우리 모두 close를 원하는 상태라는 것을 인지, 연결 종료

(state) CLOSED

 

종료과정은 시간이 많이 걸린다. 한쪽만 종료를 원한다고 바로 종료하지 않기 때문이다. 보낼게 아직 남아있는 서버측을 위해 기다려야 하고 마지막 FIN에 대한 ACK 수신

728x90
반응형

'ComputerScience > Network' 카테고리의 다른 글

TCP - 5. throughput, fairness, ECN  (0) 2022.05.10
TCP - 4. congestion control  (0) 2022.05.03
How does Skype work?  (0) 2022.04.29
TCP - 2. Reliable data transfer  (0) 2022.04.29
TCP - 1. connection-oriented-transport  (0) 2022.04.29