
데이터를 안전하고 정확하게 전달하는 데 최적화된 프로토콜
연결 지향 (Connection-oriented): 데이터 주고받기 전에 송신측과 수신측이 서로 연결되어 있는지 확인 (3-Way Handshake)
신뢰성 보장: 패킷이 손실되면 재전송을 요청하고, 순서가 바뀌면 순서를 바로잡을 수 있음
흐름 제어 (Flow Control): 수신자의 처리 속도에 맞춰 데이터 전송량을 조절
혼잡 제어 (Congestion Control): 네트워크가 혼잡할 때 전송 속도를 줄임
속도보단 신뢰성, 무결성이 중요할 때 사용하는 프로토콜
사용 예시
TCP와 다르게 신뢰성보다는 속도와 효율성을 중시하는 프로토콜
비연결형 (Connectionless): 연결 설정 과정 없이 데이터를 일방적으로 보냄
(잘 도착했는지 확인하는게 없음. 서로 보내놓기만 함)
낮은 오버헤드: TCP와 달리 혼잡 제어나 흐름 제어를 하지 않으므로 헤더가 가볍고 빠름
데이터 경계 중심: 데이터를 메시지 단위로 처리하며, 수신측에서 순서가 보장되지 않거나 일부 데이터가 유실될 수 있음
Checksum 제공: 최소한의 오류 검출 기능만 수행
사용 예시
TCP는 데이터를 송수신하기 전, 클라와 서버가 연결되기 위해 3-way handshake를 함
마찬가지로 연결을 끊기 전에는 4-way handshake를 함
LISTEN상태로 다른 클라의 접속요청을 기다림클라 -- SYN --> 서버
클라이언트가 서버에게 서버 접속을 요청하는 패킷 SYN(Synchronize)을 보냄
이때 클라는 임의의 시퀀스 번호(ISN, Initial Sequence Number)를 생성하여 함께 보내고 SYN_SENT 상태가 됨
서버 -- ACK + SYN --> 클라
서버는 클라의 요청을 받고 클라로 ACK을 보냄.
이때 받은 ISN번호에 1을 더한 값을 ACK번호로 해서 잘 받았음을 알림
그리고 서버도 클라에게 연결하기 위해 ISN을 새로 만들고 SYN을 클라에게 보냄
서버는 SYN_RECEIVED 상태가 됨
클라 -- ACK --> 서버
클라는 서버가 보낸 ACK을 통해 자신의 SYN이 잘 갔는지 확인하게 됨
그리고 서버가 보낸 SYN에 대한 응답으로 ACK을 마찬가지로 ISN에 1더해서 서버로 보냄
이 단계까지 끝나면 연결이 완료되어 양쪽 모두 ESTABLISHED 상태가 되고 본격적인 데이터 전송이 가능해짐
연결을 종료하기 전에 상대방도 보낼 데이터가 남았는지 확인하고 종료하는 과정
연결 시작은 보통 클라이언트에서 시작하지만, 종료는 클라/서버 둘 다 시작 가능
클라가 먼저 종료 요청하는 상황
클라 -- FIN --> 서버
클라는 이제 연결을 종료하겠다는 FIN플래그를 서버에 보냄
클라는 서버의 응답을 기다리는 FIN_WAIT_1 상태가 됨
서버 -- ACK + 남은데이터 --> 클라
서버는 클라이언트의 종료 요청을 확인하고 ACK를 보냄
그리고 아직 보낼 남은 데이터가 있다면 마저 보냄
이렇게 남은 데이터를 보내야하는 과정이 필요해서 연결을 바로 끊지 않고 한 단계가 더 있는 것
서버는 CLOSE_WAIT 상태가 되고, 클라는 ACK받고 서버의 FIN을 기다리는 FIN_WAIT_2 상태가 됨
서버 -- FIN --> 클라
데이터 다 보낸 서버는 클라에게 FIN을 보냄
서버는 클라의 마지막 응답을 기다리는 LAST_ACK 상태가 됨
클라 -- ACK --> 서버
클라는 서버의 FIN 받고 ACK을 보냄
서버는 마지막 ACK을 받고 CLOSED상태가 됨
클라는 혹시 모를 지연 패킷에 대비해 일정 시간 대기하는 TIME_WAIT 상태를 거치고 종료됨
TIME_WAIT 상태가 필요한 이유
지연 패킷 처리
연결은 이미 종료되었는데 서버가 보낸 마지막 데이터 패킷이 지연으로 늦게 도착하면, 이 패킷은 손실됨. 그래서 바로 연결 안 끊고 조금 기다림
마지막 ACK 유실 대비
클라이언트가 보낸 마지막 ACK가 서버에 도달하지 못하면, 서버는 계속 LAST_ACK 상태에 갇혀 FIN을 재전송하게 됨.
TIME_WAIT 상태가 있어야만 클라가 이 재전송된 FIN에 다시 응답해줄 수 있음
TIME_WAIT은 보통 연결종료를 요청한 쪽에서 상태가 되는데, 종료 바로 못하고 소켓도 쌓이고 리소스를 잡아먹게 됨. 서버에서 하기엔 너무 비효율적.
그래서 보통 클라에서 연결종료를 요청하는 식으로 한다
ACK은 잘 받았다는 신호
NACK은 수신측에 데이터가 도착하긴 했지만, 오류가 있거나 순서가 맞지 않아 중간에 패킷이 빠진 것을 발견했을 때 송신측에 알리는 신호
TCP는 표준적으로 ACK가 오지 않거나 동일한 번호의 ACK가 중복해서 오는 상황(Duplicate ACK)을 통해 패킷 유실을 감지
블루투스/Wifi/5G 같은 무선 통신은 물리적인 환경 특성상 에러가 잦기 때문에, 하위 계층(MAC/PHY)에서 NACK을 활용하여 에러 발생 시 즉각적으로 재전송
즉, TCP는 ACK을 받아야 잘 보냈음을 확인하고, ACK이 안 오면 잘못됨을 감지하고 다시 보냄.
무선통신은 평소에 그냥 잘 보낸다 생각하며 보내다가 NACK 받으면 그 때 다시 보냄
참고로, TCP는 4계층이고 무선통신은 1~2계층에서 작동