3-Way-Handshake와 4-Way-Handshake

네트워크를 사용한 통신에서 TCP 통신을 하는 경우, 3-way-handshake라는 과정을 거친다.

TPC/IP 프로토콜을 이용해서 통신하는 두 종단간에 데이터 전송 전 정확한 데이터 전송을 보장하기 위해 사전에 연결하는 과정이다.

연결 성립(Connection Extablishment)

  1. 클라이언트는 서버에 접속을 요청하는 SYN(a) 패킷을 보낸다.
  2. 서버는 클라이언트의 요청인 SYN(a)을 받고 클라이언트에게 요청을 수락한다는 ACK(a+1)과 SYN(b)가 설정된 패킷을 클라이언트에게 발송한다.
  3. 클라이언트는 서버의 수락 응답인 ACK(a+1)과 SYN(b) 패킷을 받고 ACK(b+1)을 서버로 보내면 연결이 성립(establish)된다.

연결 종료(Connection Termination)

TCP 통신에서 3-way-handshake를 통한 연결을 해제하는 과정이다.

  1. 클라이언트가 연결을 종료하겠다는 FIN 플래그를 전송한다.
  2. 서버는 클라이언트의 요청(FIN)을 받고 알겠다는 확인 메시지로 ACK를 보낸다.
    2-1) 그리고 나서는 데이터를 모두 보낼 때까지 잠깐 TIME_OUT이 된다.(서버측 :: 자신의 통신이 끝날 때까지 기다리며 서버는 해당 포트에 연결되어 있는 Application에게 close() 을 요청한다.)
  3. 데이터를 모두 보내고 통신이 끝났으면 연결이 종료되었다고 클라이언트에게 FIN 플래그를 전송한다.(close() 요청을 받은 Application은 종료 프로세스를 진행하고 FIN 패킷을 Client에게 전송!)
  4. 클라이언트는 FIN 메시지를 확인했다는 메시지(ACK)를 서버에게 보낸다.
    4-1) 클라이언트는 아직 서버로부터 받지 못한 데이터가 있을 것을 대비해 일정 시간 동안 세션을 남겨놓고 잉여 패킷을 기다리는 과정을 거친다.(TIME_WAIT)[TIME_WAIT에서 일정 시간이 지나면 close 된다.]
  5. 클라이언트의 ACK 메시지를 받은 서버는 소켓 연결을 close 한다.

연결 설정과 종료 단계에서 차이가 나는 이유는 클라이언트가 데이터 전송을 마쳤다고 하더라도 서버는 아직 보낼 데이터가 남아있을 수 있기 때문이다.
따라서 일단, 클라이언트는 FIN에 대한 확인 응답인 ACK를 먼저 보내고, 데이터를 모두 전송한 후 서버 자신도 FIN을 보내기 때문이다.

클라이언트의 FIN 전송 후 ACK를 기다리는 FIN_WAIT1과 서버의 ACK를 받은 후 서버의 FIN을 기다리는 FIN_WAIT2는 일정 시간 후 TIME_OUT이 되면 스스로 연결을 종료한다.
그러나 CLOSE_WAIT은 Application에서 close()를 적절하게 처리해주지 못하면 CLOSE_WAIT 상태로 계속 기다리게 된다. CLOSE_WAIT 상태인 연결이 많아지면 Hang이 걸려 더 이상 연결을 하지 못하는 경우가 생긴다.

[Hang이 뭘까…?]

SYN Packet과 ACK Packet란?

SYN :: synchronize sequence number
ACK :: acknowledgement

TCP Header에는 Control Bit(플래그 비트, 6bit)라는 부분이 존재한다. 각각의 비트들은 의미를 가지고 있으며, Urg-Ack-Psh-Rst-Syn-Fin 이다. 해당 위치의 비트가 1이면 해당 패킷이 어떠한 내용을 담고 있는 패킷인지를 나타낸다.
ex)
SYN 패킷일 경우에는 000010이 되고
ACK 패킷일 경우에는 010000이 된다.

왜 패킷의 종류가 두개인가?

일단 연결을 성립하려면 서로 통신이 가능한지를 먼저 파악하기 위해 패킷을 먼저 주고받아야 한다는 것까지는 이해가 쉽다. 그런데 두 종류의 패킷을 주고 받는다. 이는 요청응답에 대한 패킷을 주고 받아야 하기 때문에 두 종류인 것이다.

2-way가 아니고 3-way인 이유는??

비유를 들어보자.
클라이언트가 자신의 목소리가 들리는지 물어본다.(SYN)
서버는 클라이언트의 목소리가 들린다고 말한다.(SYN+1) 그리고 자신의 목소리가 들리는지 물어본다.(ACK)
클라이언트는 서버의 목소리가 들린다고 말한다.(ACK+1)

이런 과정인 셈이다. TCP Connection은 양방향성 Connection이다. 클라이언트에서 서버에게 존재를 알리고 패킷을 보낼 수 있다는 것을 알리듯, 서버에서도 클라이언트에게 존재를 알리고 패킷을 보낼 수 있다는 신호를 보내야 한다. 그렇기 때문에 2-way-handshake로는 부족하므로 3-way-handshake를 사용한다.

sequence number가 난수인 이유는?

처음 클라이언트에서 SYN 패킷을 보낼 때 Sequence Number에는 랜덤한 숫자가 담겨진다.
초기 sequence number를 ISN이라고 한다. ISN이 0부터 시작하지 않고 난수를 생성해서 number를 설정하는 이유는 무엇일까?
Connection을 맺을 때 사용하는 포트(port)는 유한 범위 내에서 사용하고 시간이 지남에 따라 재사용된다. 따라서 두 통신 호스트가 과거에 사용된 포트 번호 쌍을 사용하는 가능성이 존재한다. 서버측에서는 패킷의 SYN을 보고 패킷을 구분하게 되는데 난수가 아닌 순차적인 number가 전송된다면 이전의 connection으로부터 오는 패킷으로 인식할 수 있다.
이러한 문제가 발생할 가능성을 줄이기 위해 난수로 ISN을 설정하는 것이다.

참고