TCP와 UDP 개요
인터넷 환경에서 가장 중요한 4계층 프로토콜들이다.
TCP와 UDP
- TCP에만 연결(Connection, Session) 개념이 있다.
- 연결지향(Connection Oriented)
연결 (Connection, Session)
- 연결은 매우 논리적이다.
- 그래서 TCP 연결은 Virtual Circuit라고도 한다.
💡 아래는 강사님 의견이므로, 네트워크를 깊게 공부한 사람은 의견이 다를 수 있다.
- 연결은 결과적으로 순서번호로 구현된다.
- 앞서 세그먼트에 순서를 붙였던 것이 순서번호다.
- 이 순번은 세그먼트 사이즈의 바이트 수만큼 증가한다.
- 1을 보냈는데 용량이 400이라면 401이 된다.
- 바이트 수만큼 시퀀스 번호(순서번호)가 증가하게 되어 있다.
- 연결은 ‘상태(전이)’ 개념을 동반한다.
- 예를 들어, 통화를 한다면 통화하기 전, 통화 연결, 통화를 종료한 후가 있을 것이다.
- TCP는 배려남, UDP는 배려가 없는 나쁜 남자에 비유할 수 있다.
- 상대가 못 받으면 TCP는 보내지 않는다.
- UDP는 상대가 받든지 말든지 무조건 보낸다.
TCP
- Client와 Server로 나뉜다.
- 클라이언트는 연결을 하는 주체
- 서버는 기다리고 있다 연결을 받는다.
- Server는 연결을 대기하고 있다.
- 웹 서버는 기본적으로 TCP 80번을 사용한다.
- listen 상태의 소켓을 생성하고 열어서 연결 대기
- Client(프로세스)가 소켓을 생성해서 오픈한다.
- 프로세스는 자신의 식별자인 PID를 갖는다.
- 소켓을 열면 OS가 소켓에 TCP 포트 번호를 부여한다. (번호는 남는 것으로 랜덤하게 부여됨)
- TCP(와 UDP) 통신을 하려면 IP 주소와 포트 번호를 알아야 연결을 개념적으로 시도해볼 수 있다.
- 클라이언트가 연결 Request를 보냈는데 Server에서 연결 대기를 하고 있지 않다면, 커널의 TCP 계층에서 연결을 못 받아준다는 답이 간다.
→ 운영체제 수준에서 자동으로 이루어진다.
UDP
- 연결이라는 개념은 없지만, 구조는 비슷하다.
- 특정 포트 번호를 지정할 것인지 아무거나 available한 것을 달라고 할 것인지 정도의 차이만 있다.
TCP 연결 과정
3-way handshaking
가정: 클라이언트와 접속 대기 중인 서버가 있다.
- RTT가 50ms 걸렸다고 가정한다면, 응답하는 데 걸리는 시간을 제외하고 오고 가는데 각각 약 20ms 정도 걸렸다는 이야기이다.
- 이때 통신되는 단위가 Segment이다.
- 여기서의 Segement는 Payload가 없다. → 단순 내부 연결 관리 목적의 세그먼트
- 연결 과정 (3-way handshaking)
- Client에서 랜덤으로 Sequence Number(1000)를 생성한다.
- 이렇게 생성한 번호를 Server에게 알려준다. (SYN)
- Server도 랜덤으로 Sequence Number(4000)를 생성하고, 클라이언트가 보낸 번호에 1을 증가시켜서 응답한다.
- 이때, Server가 생성한 번호도 함께 보낸다.
- Client도 Server가 보낸 번호에 1을 증가해서 응답한다.
- Client와 Server의 연결 사이에 시간 차가 있다.
- Client는 Server에게 ACK를 받으면 연결이 완료되었다고 판단
- Server는 최종적으로 Client에게 ACK를 받은 시점에 연결이 완료되었다고 판단
- 즉, 클라이언트와 서버가 각각 연결이 완료되었다고 판단하는 시점이 약 20~25ms의 시간 차가 생긴다.
- TCP 연결의 실체는?
- Seq 번호 교환
- 정책 교환
- 정책에는 여러 가지가 있다.
- Seq 번호+1 한 것
- Maximum Segment Size
- 실제로 전선을 서버와 클라이언트와 물리적으로 연결하는 것이 아닌, 논리적 연결이다.
TCP 연결 종료 및 상태변화
- 특별한 이유가 없다면 Client가 행동이 Active하다.
- 연결을 하자고 하는 것도, 끊겠다고 하는 것도 Client여야 한다.
- 만약 Server가 연결을 끊겠다고 하는 것은 특수한 경우다.
4-way handshaking
가정: 클라이언트와 서버는 서로 연결된 상태이다.
- 종료 과정 (4-way handshaking)
- 클라이언트가 연결을 끊자고 FIN을 보낸다.
- 서버는 ACK를 보낸다.
- 클라이언트는 ACK를 받으면 FIN_WAIT2 상태로 넘어가면서 FIN+ACK를 기다린다.
- 서버가 FIN+ACK를 보내면, 클라이언트는 TIME_WAIT 상태가 된다.
- TIME_WAIT가 발생한다는 것은 누군가 연결을 끊자고 할 때, 연결이 최종적으로 완료되기 전에 발생한다.
- 만약 서버 측에서 TIME_WAIT 상태가 발생한다면 서버가 연결을 끊자고 했단 건데, 이러면 어플리케이션 프로토콜 설계가 정상적이지 않은 상황인 것이다.
- 서버는 CLOSE_WAIT 상태로 클라이언트가 보낼 마지막 ACK를 기다린다.
- 클라이언트가 ACK를 보내고 서버에 도착하면 최종적으로 연결이 종료된다.
- 클라이언트는 일정 시간이 지난 후 CLOSED되고 소켓이 회수된다.
- 어플리케이션 프로토콜을 설계할 때 서버 측에서 연결을 끊게 하지 말고, 클라이언트가 먼저 끊게 하자.
- 소켓은 유한한 자원이기 때문에 회수되어야 한다.
- 자신이 연결을 끊자고 하면 소켓 회수가 바로 안 되기 때문이다.
TCP (연결) 상태 변화
TCP 트랜지션 상태 변화에 대한 다이어그램
- 처음에 소켓은 닫혀있으므로 열어준다.
- 소켓은 파일이니 Create 개념을 적용하는게 맞겠지만,
- 있는 것 중에 번호를 부여해서 열어야 하다 보니 Create라는 표현이 아닌 Closed라고 주로 표현한다.
- Server는 LISTEN 트랙을 탄다.
TCP, UDP 헤더 형식과 활용
UDP 헤더 형식
- 혼잡제어를 하지 않는다.
- 수신하는 측의 버퍼가 얼마나 남았는지(Window Size) 등도 고려하지 않는다.
- UDP를 사용해야 하는 경우
- 예를 들어, IPTV의 어떤 영상을 송출해주는 서버가 있다. 해당 서버에 연결되어 있는 수많은 사용자들은 각자 속도가 다를 것이다. 속도가 느린 사용자에게 맞추면 속도가 빠른 사용자는 손해를 보게 된다.
UDP의 활용
- UDP는 멀티미디어 데이터 전송에 최적화되어 있는 측면이 있다.
- HTTP3 에도 UDP가 활용된다.
게임 서버 개발
- TCP를 이용해 게임 서버 간에 동기화를 하게 되면, 하향평준화 문제가 발생한다.
- 한 사용자가 느려지면 전체가 전부 느려지게 프로토콜을 구성할 수밖에 없다.
- 따라서 동기화를 위해 UDP를 이용해 게임 서버 간 구현을 많이 한다.
- TCP가 가지고 있는 혼잡 제어 기능은 직접 구현하면 된다.
TCP ‘연결’이라는 착각
💡 파일 다운로드 중 LAN 케이블을 분리했다가 다시 연결하면 TCP 연결은 어떻게 될까?
- 소켓 프로그래밍을 할 때는 연결이 되어있는지 지속적으로 검사한다.
- TCP 3-way handshake가 끝났음에도 계속해서 재확인한다.
- 이 행위를 하트 비트라고 한다.
- (RFC 문서에서는) 재전송 타이머의 기본 근사 값은 대략 3다. 하지만 대부분의 운영체제들은 1초 미만이다.
- 재전송 타이머 만료 후에도 확인 응답을 받지 못한 경우 세그먼트를 재전송하고 RTO(Retransmission Time-Out) 값은 두 배로 증가한다.
- 예를 들어 1초 > 2초 > 4초 > 8초 > 16초 간격으로 재전송한다.
- 보통 최대 5회 재전송을 시도하고 5회 이상 모두 실패할 경우 전송 오류가 발생한다.
TCP 연결과 게임 버그
- 어떤 MMORPG 게임에서 아이템 복제 버그가 발생했다.
- 과거 TCP 연결의 착각을 이용한 해킹이 있었다.
- 이는 논리적 TCP 연결과 물리적 링크 간 차이를 이용한 시간차 공격이라고 볼 수 있으며, 연결이 사실은 End-point의 주관적 판단에 불과하다는 것을 보여준다.
TCP 연결은 보안성이 없다
- 보안의 3대 요소
- 기밀성: 누가 도청할 수 있는가?
- 무결성: 누군가 조작(변조)할 수 있는가?
- 가용성: 재해 대책과 관련된 것
- TCP 연결은 보안성이 없으므로, 신뢰할 수 없다.
Reference
외워서 끝내는 네트워크 핵심이론 - 기초 강의 - 인프런