본문 바로가기
컴퓨터과학/네트워크

3-5. 전송(Transport) 계층: TCP 2

by 니키티스 2021. 10. 28.

해당 글은 한양대학교 이석복 교수님의 과목 "컴퓨터 네트워크"를 공부하고 작성한 글입니다. 틀린 내용이 있으면 덧글로 지적해주시면 감사하겠습니다.

컴퓨터 네트워크 - 한양대학교 | KOCW 공개 강의

 

컴퓨터네트워크

인터넷을 동작시키는 컴퓨터네트워크 프로토폴을 학습한다.

www.kocw.net

 


 

이전 글(3-4. 전송(Transport) 계층: TCP (tistory.com))에 이어 이번에는 TCP의 중요한 기능인 Flow control, Congestion control을 배워보자.

 

1. 흐름 제어(Flow control)

데이터의 전송 속도는 어느 정도가 적절할까?

당연히 데이터는 빨리 보내면 보낼수록 좋을 것 같지만, 실상은 그렇지 않다.

아무리 빨리 보내도 수신자가 처리할 수 없을 정도로 빠르게 전달되면 결국 처리할 수 없기 때문이다.

 

A에서 B로 데이터를 전송할 때, 전송자는 데이터의 전달 속도를 마음대로 조절할 수 있다. 그러나 유의미한 결과를 내려면 B가 받을 수 있는 속도 이상으로 전송하면 안 된다. 모든 호스트는 send 버퍼와 recv 버퍼를 갖는다. 그런데 B가 recv 버퍼에 들어 있는 데이터를 처리하는 것보다 A가 데이터를 전송하는 것이 더 빨라지게 되면 이후의 데이터는 수용할 수 없이 버려지게 될 것이다.

 

예를 들어 A가 10바이트를 전송하려고 하는데 B에 recv 버퍼에 1바이트밖에 빈 공간이 남지 않았다면 수신할 수가 없다.

따라서 TCP에서는 이를 해결하기 위해 피드백 시에 Header에 recv 버퍼의 크기를 기록하여 전송하게 된다.

 

만약 수신 측의 recv 버퍼가 꽉 찼을 경우 송신하는 측에서는 데이터를 전송하지 않는다. 이렇게 전송자가 너무 많이, 빨리 전송하여 수신자의 버퍼가 넘치는 일이 없도록 하는 것을 흐름 제어(Flow control)이라 한다.

흐름 제어(Flow control)는 중요한 기능이지만, 위에 말했던 것처럼 recv 버퍼의 크기를 기록하는 간단한 방법으로 구현할 수 있다.

 

양인가, 속도인가

흐름 제어(Flow control)라 하면 보내는 양을 제한하는 것인지 보내는 속도를 제한하는 것인지 의미가 모호하다.

도대체 보내는 양을 줄이라는 것인가, 보내는 속도를 제한하는 것인가?

 

그러나 잘 생각해보면 두 개는 같은 말이라는 것을 알 수 있다.

전송속도는 10 Mbps와 같이 표현할 수 있는데, 여기서 bps는 bits per second, 즉 초당 비트 전송량과 같다(Mbps는 Mega(10^6) bits per seconds). 속도는 단위 시간당 전송량이다. 같은 시간 안에 보내는 양이 많아지면 보내는 속도도 동시에 올라가기 마련이다.

흐름 제어에서 recv 버퍼 크기 이상으로 데이터를 전송할 수 없다는 것은 한 번에 패킷을 보낼 수 있는 양이 현재 남은 recv 버퍼 크기로 제한된다는 것이고, 지속적으로 패킷의 전송량이 줄어들게 되면 전송속도도 줄어들게 된다.

즉, 흐름 제어(Flow control)는 전송량을 제한함으로써 전송속도도 낮추게 된다.

 

동작 원리

TCP 세그먼트 구조

동작 원리는 간단하다. 전송 측이 수신하는 측의 recv 버퍼의 크기보다 더 많이 보낼 수 없게 하는 것이다.

다시 TCP 세그먼트 구조를 보면, 네 번째 줄에 Receive window를 볼 수 있는데 이것이 바로 현재 남은 recv 버퍼의 크기를 가리킨다.

 

A에서 B로 데이터를 전송한다고 하자. B의 버퍼에서 이용 가능한 공간이 10바이트 남았다면, 헤더를 통해 정보를 전달받은 A는 많아봐야 10바이트만 보낼 수 있다.

B의 버퍼에서 이용 가능한 공간이 2바이트 남았다면 B의 세그먼트로 전달받고 A도 최대 2바이트만 전송 가능하다.

B의 버퍼가 꽉 차면 버퍼에 이용 가능한 공간이 0바이트 남은 것이므로 A는 데이터를 전송하지 않아야 한다.

 

여기서 문제가 생기는데, B의 버퍼에 공간이 하나도 없으면 A는 데이터를 전송할 수 없다. 그러나 A가 아무런 메시지도 보내지 않으면 언제 B의 버퍼가 비는지 알 수 없다. B에 메시지를 보내고 ACK가 돌아올 때 recv 버퍼의 상태를 알 수 있는데, A에서 메시지가 오지 않으면 A는 B의 recv 버퍼의 상태도 알 수가 없기 때문이다.

 

이 경우, 남은 버퍼의 상태를 어떻게 알릴 수 있을까?

TCP에서는 전송자(sender)가 정기적으로 더미 데이터를 보낸다. 아무 의미가 없는 1바이트짜리 데이터를 보내는데, 이렇게 세그먼트를 전송하여야 피드백을 통해 수신자의 버퍼에 이용 가능한 공간이 얼마나 남았는지 알 수 있기 때문이다.

 

결국 흐름 제어(Flow control)는 수신자(receiver)가 얼마나 공간이 남았는지를 직접 알려주기 때문에 구현이 단순하게 이루어진다. 그러나 이후 나오게 될 혼잡 제어(Congestion control)의 경우에는 그렇지 않아 문제가 복잡하다. 이는 다음 포스팅에서 다룰 예정이니 이번 포스팅에서는 넘어가자.

 

2. 연결 설정(Connection management)

TCP에서의 버퍼간 데이터 전달 구조. Send 버퍼의 시퀀스 번호가 상대 Recv 버퍼의 시퀀스 번호로 연결된다.

TCP 통신 과정에서는 세그먼트의 순서가 중요하기 때문에 Seq #(Sequence number; 시퀀스 번호)가 필요하다. TCP는 기본적으로 양방향 통신이다.

 

A의 send 버퍼에서 데이터를 전송하면 B의 recv 버퍼가 데이터를 받는다. 따라서 A의 send 버퍼의 Seq #는 B의 recv 버퍼의 Seq #와 같다.

반대로 B의 send 버퍼에서 데이터를 전송하면 A의 recv 버퍼가 받으므로, B의 send 버퍼의 Seq #는 A의 recv 버퍼의 Seq #와 같다.

 

네트워크 통신에서 이러한 과정이 자연스럽게 이루어지기 위해서는 무작정 메시지를 회선을 따라 보내기만 하면 되는 것이 아니라, 버퍼(send buf, recv buf)를 만들어주고 서로 상대에게 Seq #를 알려주는 작업이 필요하다. 이러한 준비 작업이 이루어져야만 네트워크 엣지(Network edge) 간에 정상적으로 통신이 이루어진다. 이러한 준비 작업을 하는 것이 "연결(Connection) 과정"으로 TCP에서 전송자(sender)와 수신자(receiver)는 데이터 세그먼트를 주고받기 이전에 연결(Connection)을 구축해야 한다.

 

TCP 3-Way Handshake

TCP 연결 과정(3-way handshake)

TCP에서는 클라이언트와 서버 간에 연결을 구축하기 위해 3-way handshake 방법을 사용한다.

3-way handshake는 이름 그대로 세 번 '악수'하는 과정으로 연결을 구축한다.

그 세 과정은 다음과 같다.

 

  1. SYN: 클라이언트가 서버에 연결을 요청
    • 클라이언트의 Seq #를 서버에 알려준다.
    • SYN 메시지를 보낸다는 것은 TCP 커넥션을 열기를 요청하는 것이다.
    • TCP Header에 있는 syn 신호를 통해 올릴 수 있다.
  2. SYN/ACK: 서버가 클라이언트에게서 SYN을 받고 SYNACK 세그먼트를 전송
    • 서버의 Seq #를 클라이언트에 알려준다.
    • 이 과정에서 서버가 버퍼를 만든다.
    • TCP Header에 있는 syn 신호ack 신호를 이용한다.
  3. ACK: 클라이언트가 SYNACK를 받고 서버에 ACK를 보내줌
    • ACK 과정에서는 클라이언트가 서버에 실제 데이터를 담아 보낼 수 있다.
    • 왜 SYNACK 과정과 ACK 과정이 필요할까?
      • 클라이언트는 두 번째 과정 SYNACK를 통해 제대로 메시지가 전송됨을 알 수 있다.
      • 그러나 서버는 ACK 과정이 없으면 메시지가 전송되긴 하지만 정상적으로 전송되었는지 알 수 없기 때문.

 

TCP 연결 끊기(4-way Handshake)

3-way handshake가 3번 메시지가 오고 가서 3-way라면, TCP 연결 종료는 4번 메시지가 오고 가므로 4-way handshake라 한다.

 

TCP 연결 종료 과정(4-way handshake)

 

  • FIN: 클라이언트서버에게 FIN을 전송
    • 클라이언트 장치가 서버에게 FIN을 보내서 연결 종료를 알린다.
  • ACK: 서버클라이언트에게 ACK를 전송
    • 클라이언트 to 서버 연결 종료 확인 과정 
    • 서버는 클라이언트의 연결 중단 요청을 확인하고 피드백으로 ACK를 보내어준다.
  • FIN: 서버클라이언트에게 FIN을 전송
    • 이번엔 반대로 서버의 연결 중단을 클라이언트에게 고지한다.
    • 클라이언트가 FIN을 수신하면 잠시 동안 timed wait 상태가 되어 연결 종료를 통지받고도 한참 동안 종료되지 않는다.
  • ACK: 클라이언트서버에게 ACK를 전송
    • 서버 to 클라이언트 연결 종료 확인 과정
    • 서버가 ACK를 받고 나면 TCP 연결이 종료된다.

 

클라이언트가 timed wait 상태인 동안에는 연결 종료를 통지받고도 한참 동안 종료되지 않는다.

그 이유는 서버에서 전송한 FIN이 도착한다는 보장이 없기 때문이다. FIN이 정상적으로 도착하지 않아 서버에서 timeout이 발생하면 서버는 클라이언트에게 다시 FIN을 보내고 ACK를 기다린다.

클라이언트가 닫혀 있으면 FIN을 받고 ACK를 보내줄 수 없으므로 충분한 시간 동안 클라이언트를 종료하지 않고 기다리게 되는데, 이 과정이 바로 timed wait이다.

 

 

 

댓글