[Network] TCP 3 Way-Handshake & 4 Way-Handshake

임아연·2021년 8월 7일
0

CS Study - Network

목록 보기
1/4

TCP(Transmission Control Protocol)

TCP는 네트워크 계층 중 전송 계층에서 사용하는 프로토콜로서, 장치들 사이에 논리적인 접속을 성립(extablish)하기 위하여 연결을 설정하여 신뢰성을 보장하는 연결형 서비스이다.

TCP의 특징

  • 인터넷 상에서 데이터를 메세지의 형태(세그먼트 라는 블록 단위)로 보내기 위해 IP와 함께 사용하는 프로토콜이다.
    • TCP와 IP를 함께 사용하는데, IP가 데이터의 배달을 처리한다면 TCP는 패킷을 추적 및 관리한다.
  • 연결형 서비스로 가상 회선 방식을 제공한다.
    • 3-way handshaking 을 통해 연결을 설정하고, 4-way handshaking 을 통해 연결을 해제한다.
  • 흐름제어 및 혼잡제어를 제공한다
  • 흐름제어
    • 데이터를 송신하는 곳과 수신하는 곳의 데이터 처리 속도를 조절하여 수신자의 버퍼 오버플로우를 방지하는 것
    • 송신하는 곳에서 감당이 안되게 많은 데이터를 빠르게 보내 수신하는 곳에서 문제가 일어나는 것을 막는다.
  • 혼잡제어
    • 네트워크 내의 패킷 수가 넘치게 증가하지 않도록 방지하는 것
    • 정보의 소통량이 과다하면 패킷을 조금만 전송하여 혼잡 붕괴 현상이 일어나는 것을 막는다.
  • 높은 신뢰성을 보장한다.
  • UDP보다 속도가 느리다.
  • 전이중(Full-Duplex), 점대점(Point to Point) 방식이다.
    • 전이중
      • 전송이 양방향으로 동시에 일어날 수 있다.
    • 점대점
      • 각 연결이 정확히 2개의 종단점을 가지고 있다.
    • 멀티캐스팅이나 브로드캐스팅을 지원하지 않는다.
  • 연속성보다 신뢰성있는 전송이 중요할 때에 사용된다.

TCP의 연결 설정 및 해제 과정

TCP Handshake는 TCP/IP 프로토콜을 이용해서 통신을 하는 응용 프로그램이 데이터를 전송하기 전에 먼저 정확한 전송을 보장하기 위해 상대방 컴퓨터와 사전에 세션을 수립하는 과정을 의미한다.

출처 : https://www.crocus.co.kr/1362

3-way handshake

TCP 통신을 이용하여 데이터를 전송하기 위해 네트워크 연결을 설정(Connection Establish)하는 과정

  1. 클라이언트는 접속을 요청하는 SYN 패킷을 보낸다.
    이때 클라이언트는 SYN 패킷을 보냄과 동시에 SYN/ACK 응답을 기다리기 위해 SYN_SENT 상태로 변하게 된다.
  2. 서버는 SYN 요청을 받고 클라이언트에게 요청을 수락하는 ACK패킷과 SYN패킷을 보내고 SYN_RCVD(SYN_RECEIVED) 상태로 변하여 클라이언트가 ACK 패킷을 보낼 때 까지 기다리게 된다.
  3. 클라이언트는 서버에 ACK패킷을 보내고 이 후 ESTABLISHED 상태가 되어 데이터 통신이 가능하게 된다.
  • SYN_RECV는 요청자가 보낸 SYN 패킷을 수신자가 제대로 받은 상태를 의미한다.
  • ISN(Initialized Sequence Number; 초기 시퀀스 번호) : SYN 패킷의 Sequence Number는 운영체제에 의해서 랜덤하게 생성된다.
  • ACK 패킷의 Acknowledgement Number는 신뢰적 데이터 전송을 위해 사용되는 것이다.
  • ACK는 수신자가 제대로 된 시퀀스 번호를 받았다는 확인의 의미이다. 다시 요청자에게 돌려줄 때의 승인 번호(Acknowledgement)는 처음 요청자가 보낸 시퀀스 번호 + 1이다.
  • 승인 번호(ACK)를 반드는 과정은 TCP를 사용하여 실제로 데이터를 주고받을 때에는 상대방이 보낸 시퀀스 번호 + 상대방이 보낸 데이터의 byte를 합쳐서 승인 번호를 만들어낸다. 즉, 내가 여기까지 받았으니, 다음에는 여기부터 보내달라는 일종의 마킹이다.
    하지만 이런 핸드쉐이크 과정에서는 데이터를 아직 주고 받지 않기 때문에 시퀀스 번호를 더할게 없고, 같은 번호로 주고 받으면 패킷의 순서를 구분할 수 없기 때문에 그냥 1을 더하는 것이다.

4-way handshake

TCP의 연결을 해제(Connection Termination)하는 과정
그냥 한 쪽에서 일방적으로 연결을 끊어버리면 다른 한 쪽은 연결이 끊어졌는지 지속되고 있는지 알 방법이 없다.
연결을 종료하기 전에 아직 다 처리하지 못한 데이터가 있을 수도 있기 때문에 양 쪽이 다 정상적으로 연결을 종료할 준비가 되었는지를 확인하는 과정이 필요하다.
=> 4 Way Handshake는 3 Way Handshake처럼 순차적으로 주고받는 방식이 아니라 상대방이 응답을 줄 때까지 대기하는 과정이 포함되어 있기때문에 중간에 뭐 하나 엇나가면 서로 계속 대기만 하고 있는 데드락(Deadlock) 상황이 연출될 수도 있다.

출처 : https://evan-moon.github.io/2019/11/17/tcp-handshake/
출처 : https://beenii.tistory.com/127

  1. 서버와 클라이언트가 TCP 연결이 되어있는 상태에서 클라이언트가 접속을 끊기 위해 CLOSE() 함수를 호출하게 된다.
    클라이언트가 CLOSE() 를 호출하면서 서버에게 FIN 패킷을 보내게 되는데, 이때 FIN 패킷에 실질적으로는 ACK도 포함되어 있다. 그리고 나서 클라이언트는 FIN_WAIT_1상태로 들어간다.
  2. 서버는 클라이언트가 CLOSE() 한다는 것을 알게되고 CLOSE_WAIT 상태로 바꾼 후 ACK segment를 전송한다.
    즉, 클라이언트가 끊을 것이라는 신호를 받았다는 의미이고 CLOSE_WAIT를 통해 자신의 통신이 끝날때까지 기다리는 상태가 된다.
  3. ACK segment를 받은 클라이언트는 FIN_WAIT2로 변환되고 이때 서버는 CLOSE() 함수를 호출하고 FIN segment를 클라이언트에게 보낸다.
  4. 서버도 연결을 닫았다는 신호를 클라이언트가 수신하면 ACK segment를 보낸 후 클라이언트는 TIME_WAIT 상태로 전환된다.
  5. 이 후 모든것이 끝나면 CLOSED 상태로 변환된다.
  • FIN 패킷에도 시퀀스 번호가 포함되어 있긴 한데, 랜덤한 값으로 생성해서 보내지 않는다.
    3 Way Handshake는 시퀀스 번호가 없는 상황에서 새로 만들어야 하는 상황이라 랜덤한 갑승로 초기화했지만, 4 Way Handshake에서는 시퀀스 번호를 새롭게 생성할 필요가 없으므로 그냥 자신이 이번에 보내야할 순서에 맞는 시퀀스 번호를 사용하면 된다.
  • 1번 과정에서 FIN 패킷에 승인 번호를 함께 묶어서 FIN+ACK로 보내는 이유는 Half-Close 라는 기법을 사용하기 때문이다.
    Half-Close 기법은 말 그대로 연결을 종료하려고 할 때 완전히 종료하는 것이 아니라 반만 종료하는 것이다.
    반만 닫겠다는 말의 의미는 연결을 종료할 때 전송 스트림과 수신 스트림 중 하나만 우선 닫겠다는 것을 의미한다.
    이후 수신자는 미처 못 보낸 데이터가 있다면 보낼 것이고, 이에 요청자는 아직 살아있는 수신 스트림을 사용하여 데이터를 처리한 후 ACK 패킷을 응답으로 보낼 수 있다.
    이후 수신자가 모든 데이터를 처리하고 나면 다시 요청자에게 FIN 패킷을 보냄으로써 모든 데이터가 처리되었다는 신호를 보내준다.
  • TIME_WAIT의 역할은 의도하지 않은 Error로 인해 연결이 DeadLock에 빠지는 것을 방지하는 것이다.

TCP 관련 질문

💡 TCP의 연결 설정 과정(3단계)와 연결 종료 과정(4단계)이 단계가 차이나는 이유는?

A. Client가 데이터 전송을 마쳤다고 하더라도 Server는 아직 보낼 데이터가 남아있을 수 있기 때문에 일단 FIN에 대한 ACK만 보내고, 데이터를 모두 전송한 후에 자신도 FIN 메시지를 보내기 때문이다.

💡 만약 Server에서 FIN 플래그를 전송하기 전에 전송한 패킷이 Routing 지연이나 패킷 유실로 인한 재전송 등으로 인해 FIN 패킷보다 늦게 도착하는 상황이 발생하면 어떻게 될까?

A. 이러한 현상에 대비하여 Client는 Server로부터 FIN 플래그를 수신하더라도 일정시간(Default: 240sec)동안 세션을 남겨 놓고 잉여 패킷을 기다리는 과정을 거친다. (TIME_WAIT 과정)

💡 초기 Sequence Number인 ISN을 0부터 시작하지 않고 난수를 생성해서 설정하는 이유는?

A. Connection을 맺을 때 사용하는 포트(Port)는 유한 범위 내에서 사용하고 시간이 지남에 따라 재사용된다. 따라서 두 통신 호스트가 과거에 사용된 포트 번호 쌍을 사용하는 가능성이 존재한다. 서버 측에서는 패킷의 SYN을 보고 패킷을 구분하게 되는데 난수가 아닌 순차적인 Number가 전송된다면 이전의 Connection으로부터 오는 패킷으로 인식할 수 있다. 이런 문제가 발생할 가능성을 줄이기 위해서 난수로 ISN을 설정한다.

✨ Reference

https://gmlwjd9405.github.io/2018/09/19/tcp-connection.html
https://beenii.tistory.com/127
https://www.crocus.co.kr/1362
https://evan-moon.github.io/2019/11/17/tcp-handshake/ => 정리가 너무 잘 되어 있는 사이트
https://github.com/WeareSoft/tech-interview/blob/master/contents/network.md#frame-packet-segment-datagram

profile
느릿느릿 꾸준하게

0개의 댓글