TCP
인터넷 상에서 데이터를 메세지 형태로 보내기 위해 IP와 함께 사용하는 프로토콜
🔸 포트(port) 상태 정보
- CLOSED: 포트가 닫힌 상태
- LISTEN: 포트가 열린 상태로 연결 요청 대기 중
- SYN_RCV: SYNC 요청을 받고 상대방의 응답을 기다리는 중
- ESTABLISHED: 포트 연결 상태
🔸 플래그 정보
- TCP 헤더에는 CONTROL BIT(플래그 비트, 6비트)가 존재한다. 6비트의 각각은 URG, ACK, PSH, RST, SYN, FIN를 의미한다.
- SYN(Synchronize Sequence Number: 000010): 연결 설정. Sequence Number를 랜덤으로 설정하여 세션을 연결하는데 사용한다. 초기에 Sequence Number를 전송한다.
- ACK(Acknowledgement: 010000): 응답 확인. 패킷을 받았다는 것을 의미한다. Acknowledgment Number 필드가 유효한지를 나타낸다.
- FIN(Finish: 000001): 연결 해제. 세션 연결을 종료시킬 때 사용되며 더 이상 전송할 데이터가 없음을 의미한다.
3 way handshake 방식 (SYN, ACK)
- TCP 통신을 이용해 데이터를 전송하기 위해 네트워크 연결을 설정하는 과정이다.
- 양쪽 모두 데이터를 전송할 준비가 되었다는 것을 보장한다.
- TCP/IP 프로토콜을 이용해 통신을 하는 응용 프로그램이 데이터를 전송하기 전에 상태방 컴퓨터와 사전에 세션을 수립하는 과정이다. 이는 정확한 전송을 보장한다.
작동방식
🔹 1단계
- 클라이언트는 서버와 연결하기 위해 SYN을 보낸다.(seq:x)
- 송신자가 최초로 데이터를 전송할 때 Sequence Number를 임의의 랜덤 숫자로 지정하고, SYN 플래그 비트를 1로 설정한 세그먼트를 전송한다.
- PORT 상태:
Client: CLOSED -> SYN_SENT로 변함
Server: LISTEN
🔹 2단계 (SYN + ACK)
- 서버가 SYN(x)을 받고, 클라이언트로 받았다는 신호인 ACK와 SYN 패킷을 보낸다.(seq:y, ACK:x+1)
- 서버가 요청을 수락했으며, 클라이언트에게 포트를 열어달라는 메세지를 전송(SYN-ACK signal bits set)
- ACK Number 필드를 Sequence Number+1로 지정하고 SYN과 ACK 플래그 비트를 1로 설정한 세그먼트를 전송한다.(Seq=y, Ack=x+1, SYN, ACK)
- PORT 상태:
Client: CLOSED
Server: SYN_RCV
🔹 3단계 (ACK)
- 클라이언트는 서버의 응답으로 ACK(x+1)와 SYN(y) 패킷을 받은 후, ACK(y+1)를 서버로 보낸다.
- 마지막으로 클라이언트가 수락 확인을 보내 연결을 맺는다.(ACK)
- 이때 전송할 데이터가 있으면 이 단계에서 데이터를 전송할 수 있다.
- PORT 상태:
Client: ESTABLISED
Server: SYN_RCV -> ACK -> ESTABLISED
전이중(full-duplex) 통신의 구성
- 1, 2단계에서는 Client->Server 방향에 대한 연결 파라미터(시퀀스 번호)를 설정하고 이를 승인한다.
- 2, 3단계에서는 Server->Client 방향에 대한 연결 파라미터(시퀀스 번호)를 설정하고 이를 승인한다.
💡 이로써 전이중 통신이 구축된다.
4 way handshake 방식
- 4-way handshake는 연결을 해제하는 과정이다. FIN(finish) 플래그를 이용한다.
- FIN: 세션을 종료시키는데 사용되며 더 이상 보낸 데이터가 없음을 나타낸다.
🔸 Termination의 종류
TCP는 대부분의 connection-oriented 프로토콜과 같은 두 가지 연결 해제 방식이 있다.
- Graceful connection relese(정상적인 연결 해제)
양쪽 커넥션이 서로 모두 커넥션을 닫을 때까지 연결되어 있다.
- Abrupt connection release(갑작스런 연결 해제)
갑자기 한 TCP 엔티티가 연결을 강제로 닫는 경우 혹은 한 사용자가 두 데이터 전송 방향을 모두 닫는 경우가 있다.
작동방식
🔹 1단계 (Client -> Server: FIN(+ACK))
- 서버와 클라이언트가 연결된 상태에서 클라이언트가 close()를 호출하여 접속을 끊는다.(혹은 끊으려 한다.)
- 이때 클라이언트는 서버에게 연결을 종료한다는 FIN 플래그를 보낸다. FIN 패킷에는 실질적으로 ACK도 포함되어 있다.
🔹 2단계 (Server -> Client: ACK)
- 서버는 FIN을 받고 확인했다는 ACK를 클라이언트에게 보내고 자신의 통신이 끝날 때까지 기다린다. (TIME_WAIT 상태)
- 서버는 ACK Number 필드를 Sequence Number+1로 지정하고, ACK 플래그 비트를 1로 설정한 세그먼트를 전송한다.
- 서버는 클라이언트에게 응답을 보내고 CLOSE_WAIT 상태에 들어간다. 아직 남은 데이터가 있다면 마저 전송을 마친 후에 close()를 호출한다.
- 클라이언트에서는 서버에게 ACK를 받은 후 서버가 FIN 패킷을 보낼 때까지 기다린다. (FIN_WAIT_2)
🔹 3단계 (Server -> Client: FIN)
- 데이터를 모두 보냈다면 서버는 연결 종료에 합의한다는 의미로 FIN 패킷을 클라이언트에게 보낸다. 그리고 클라리언트가 승인 번호를 보내줄 때까지 기다리는 LAST_ACK 상태로 들어간다.
🔹 4단계 (Client -> Server: ACK)
- 클라이언트는 FIN을 받고 확인했다는 ACK를 서버에게 보낸다.
- 아직 서버로부터 받지 못한 데이터가 있을 수 있으므로 TIME_WAIT를 통해 기다린다.(CLOSED)
- 이때 TIME_WAIT 상태는 의도치 않은 에러로 인해 연결이 데드락으로 빠지는 것을 방지한다.
- 만약 에러로 종료가 지연되다가 타임이 초과되면 CLOSED로 들어간다.
- 서버는 ACK를 받은 이후 소켓을 닫는다.(Closed)
- TIME_WAIT 시간이 끝나면 클라이언트도 소켓을 닫는다.(Closed)