외워서 끝내는 네트워크 핵심이론 - 섹션 4. L4 수준 대표주자 TCP와 UDP

dev_hee·2023년 6월 25일
0

network

목록 보기
5/6
post-thumbnail

TCP와 UDP

인터넷 환경에서 가장 중요한 4계층 프로토콜

  • TCP에만 연결 (Connection, Session) 개념이 있다.
  • 연결은 결과적으로 순서번호로 구현된다.
  • 연결은 '상태(전이)' 개념을 동반한다.
  • TCP는 배려남, UDP는 (배려 없는)나쁜 남자에 비유할 수 있다.
  • Zero Window: 어플리케이션 레벨에서 발생하는 장애 상황. 상대가 받을 수 없는 상황. TCP는 이 경우 보내지 않고, UDP는 보냄.

식별자와 단위

  • Ethernet: MAC 주소, Frame
  • Internet: IPv4 주소, Packet
  • TCP, UDP: Port 번호, Segment, Datagram
  • Application: Socket + Stream(시작은 있는데 끝을 측정하기 어려운 특징을 가짐)

TCP

클라이언트와 서버로 구성된다.
서버에서 소켓 인터페이스를 열어서 연결을 대기하고 있는다.

클라이언트에서 PID를 가진 프로세스가 소켓을 Create & Open 하여, 운영체제 입장(Kernel mode)에서 소켓에다 TCP Port 번호를 부여한다. 운영체제는 남는 번호를 임의로 생성해서 부여한다. 또는 특정 번호를 요청해서 부여할 수 있다.

연결을 대기하는 서버에서 Listen 상태의 소켓을 Create & Open 하면 서버 프로세스가 OS에게 80 TCP Port 번호를 받는다. 따라서 서버의 TCP port 번호를 알아야 연결을 시도해볼 수 있다.

만약 서버에서 연결 대기중인 프로세스 서버가 없고, 소켓도 열려있지 않은 연결 대기가 아닌 상태에서 연결 요청이 들어오면 운영 체제에서 연결을 못받는다는 응답을 보낸다. 이런 과정은 운영체제에서 자동으로 이루어진다.

TCP 연결 과정 (3-way handshaking)

연결이 결론이라면, 연결의 과정이 3-way handshaking이다.
여기서 연결은 실제 클라이언트와 서버간에 랜선이 연결된다는 것이 아니라, 논리적인 연결(Virtual Connection)이다.

세로선은 Time line, 밑으로 갈수록 시간이 흐른다.
클라이언트가 서버(192.168.0.20:80)에게 연결하기 위해 소켓을 생성 및 열기를 한다. 서버로 갔다가 돌아오는 시간(RTT)이 50ms이라고 해보자.

연결과정에서 오가는 Segment는 IP, TCP 로 이뤄진 단순 내부 연결용이다.
연결하려는 클라리언트에서 Sequence number(임의의 숫자)을 생성해서 (1)SYN (1000) 을 보낸다. (2)서버는 1을 증가 시켜서 1001를 전달한다. 그리고 서버에서 생성한 Sequence number도 함께 보낸다. (3)클라이언트는 1증가한 4001 로 응답한다. 이 때 서버와 클라이언트가 MSS(Maximum Segment Size)를 공유한다. 만약 클라이언트가 1460이고 서버가 1400이면 클라이언트가 서버에게 맞춘다.

클라이언트가 연결을 시도해서 (2) ACK를 받는 순간에 서버와 연결되었다고 판단한다. 하지만 서버는 아직 연결이 완료되었다고 판단하지 않는다. ACK을 받기 전이기 때문에고 RTT가 지난 후에야 연결되었다고 판단한다.

정리하면 TCP 연결의 실체는 다음과 같다.

  • Sequence 번호를 교환함
  • 정책 교환 (Maximum Segment Size - MSS)

TCP 연결 종료 과정 (4-way handshaking)

연결할 때보다는 더 복잡한 4-way handshaking을 한다.

특별한 이유가 없다면 클라이언트 행동이 Active하다. 연결을 요청하는 것도, 끝는 것도 클라이언트여야 한다. 서버가 연결을 요청 및 종료 하는 경우는 특수하다.

연결을 종료하기 위해서는 연결(ESTABLISED)이 전제되어야 한다. (1) 클라이언트에서 연결을 끊기 위해 FIN + ACK 을 보낸다. (2) 서버는 FIN을 받아서 ACK을 보낸다. 클라이언트는 서버에서 FIN을 보낼 때 까지 기다린다. (3) 다시 서버에서 연결을 끊기 위해 FIN + ACK 을 보낸다. (4) 클라이언트에선 FIN을 받고 ACK를 보낸다.

여기서 중요한 상태 개념이 있다. (3) 과정에서 FIN + ACK를 받으면 TIME_WAIT 상태가 된다. TIME_WAIT 상태가 의미하는 것은 연결을 끊자고 한 주체가 클라이언트라는 것이다. 서버의 상태가TIME_WAIT 발생했다면 일반적인 상황은 아니다.

TIME_WAIT > CLOSE 로 일정시간이 지나면 상태가 변경되고, CLOSE 되면 Socket을 닫는다. 사용할 수 있는 Socket 개수가 제한되어 있기 때문에 자원을 아껴야 한다.

서버는 특별한 이유가 없는한 자신이 연결을 끊지 않고, 클라이언트에게 연결 종료를 요청한다. 어플리케이션 프로토콜에서는 이런식으로 서버의 소켓 자원을 아끼기 위해 구현되어 있다. 다만 개발자가 소켓 프로그래밍을 할 때 서버에서 연결 종료하도록 개발한다면 TIME_WAIT 상태가 서버에서 발생하기 때문에 문제가 될 수 있다.

TCP(연결) 상태 변화

소켓이 처음에 닫혀있으면 생성해서 연다. LISTEN 상태는 서버에서 가진다.

연결 종료시 서버는 Passive CLOSE이고, 클라이언트는 Active CLOSE이다. 클라이언트가 연결을 먼저 종료하기 때문이다.

TCP Header 형식

Port 번호

16 bit => 2^16 개의, 즉 0 ~ 65535 사이의 번호를 가질 수 있다.
하지만 0, 65535 는 사용하지 않으므로 2^16-2 개의 번호를 포트번호로 사용 가능하다.

Port 번호는 그 번호를 사용하는 소프트웨어 프로그램이 있을 것이다.
일반적으로 어떤 소프트웨어에서 사용하는 포트 번호들은 정해져있다.
이렇게 정해져 있는 포트 번호를 Well known Ports 라고 부르며,
웹의 경우엔 80번 포트를 사용한다. 따라서 naver.com:80 라고 사용하는 것이 아닌
naver.com 만으로도 접속 가능하다.

Sequence number

일련 번호. 3-way handshaking 에서 사용된다.
전송하는 데이터의 단위가 100byte인 경우, Sequence number도 100씩 증가하게 된다.

Acknowledgment number (ACK)

서버나 클라이언트에서 전달받은 Sequence number 번호에 + 1 한 값이다.

Data offset

TCP 세그먼트 페이로드 위치를 계산할 때

Flag

TCP 의 상태를 결정할 때 사용된다.

  • ACK, SYN, FIN
  • RST : 뭔가 잘못 되었을 때 리셋하는, 연결을 끊을 때 사용함
  • PSH : TCP 통신 시 버퍼링을 하지 않고 즉시 보낸다
  • 나머지 : 혼잡 제어 부분. TCP 장애 유형(Loss, Re-Trans, Duplicated ACK, Out of order, Zero Window)이 발생했을 때 네트워크가 혼잡하다고 보는것. 이를 통제하기 위해 존재하는 플래그

Window Size

여분의 공간. TCP 수준에서 버퍼의 남는 여유 공간.
만약 이 공간이 0 까지 간다면 네트워크 속도가 처리 속도를 역전한 경우임.
이 경우는 Zero Window가 발생한 상황이고 프로세스 단에서 문제를 해결해야함

Checksum

데이터가 손상된 것이 없는지 계산하는데 사용하는 검사값

참고: https://evan-moon.github.io/2019/11/10/header-of-tcp/

UDP Header 형식

영상을 송출하는 경우 클라이언트의 네트워크 상황에 맞추지 않고 영상을 송출한다.
혼잡 제어 X, 버퍼 고려 X

클라이언트를 배려하지 않는다. 그런 이유는 영상을 사용하는 클라이언트들 중에 느린 네트워크에 맞춰서 느리게 송출하면, 빠르게 좋은 영상 볼 수 있는 사람이 손해 보기 때문에 빠르게 영상을 송출한다.

게임 서버

TCP 를 이용해 서버와 동기화 하는 경우엔 하향 평준화 된다. 한 클라이언트가 느리면 그에 맞춰지기 때문이다.
따라서 동기화를 위해 UDP 를 사용하는 것이 적합하다. 게임 서버에선 UDP를 기반으로 혼잡 제어 로직을 구현해서 개발하면 된다.

HTTP3

차세대 프로토콜인 HTTP3는 UDP 기반이다. 게임 서버와 유사한 이유로 UDP를 사용한다.

TCP "연결"이라는 착각

파일 다운로드 중 LAN 케이블을 분리했다가 다시 연결하면 TCP연결은 어떻게 될까?

L4 TCP 연결 중, L1의 LAN선을 뽑은 상황이다.

결론은 랜선이 끊어져도 일정 시간 동안 TCP 연결이 유지된다!
LAN선을 얼마나 오래 뽑아놨는지랑 관련이 있다.

프로세스에서 연결이 되어 있는가를 지속적으로 재확인(HeartBeat)한다.

TCP "연결"이라는 착각

하지만 대부분의 운영체제에서는 스스로 연결을 끊어버린다.

  • 재전송 타이머의 기본 근사 값은 대략 3초이다. 하지만 대부분 운영체제들은 재전송 타이머가 1초 미만이다.

  • 재전송 타이머 만료 후에도 확인 응답을 받지 못한 경우 세그먼트를 재전송하고 RTO(Retransmission Time-Out)을 2배로 증가시킨다.

만약 1초 정도 랜선을 뽑고 다시 연결한다면 L4의 논리적 연결은 지속된다.
이렇게 1초간 랜선이 끊기는 것을 충격이라고 하며 그동안 버퍼에 저장한 데이터를 사용하거나 한다.
무선에서는 항상 충격이 발생한다. 하지만 중간에서 버퍼가 완화해주기 때문에 끊김없이 느껴진다.

  • 예를 들어 1초 > 2초 > 4초 > 8초 > 16초 간격으로 재전송한다.
  • 보통 최대 5회 재전송을 시도하고 5회 이상 모두 실패할 셩우 보통 전송 오류가 발생한다.

TCP 연결과 게임 버그

연결은 주관적이기 때문에 속이면 속아 넘어가는 보안성이 전혀 없는 판단이다.

  • 어떤 MMORPG 게임에서 아이템 복제 버그가 발생했다.
  • 이는 논리적 TCP 연결과 물리적 링크간 차이를 이용한 시간차 공격이라 볼 수 있으며 연결이 사실은 End-point의 주관적 판단에 불과하다는 것을 보여준다.
  • 한번 ESTABLISHED 상태가 되면 연결 되었다고 판단해버린다.
  • TCP의 연결은 보안성이 없다. (기밀, 무결, 가용) 연결은 신뢰할 수 없다.
profile
🎨그림을 좋아하는 FE 개발자👩🏻‍💻

0개의 댓글