티스토리 뷰

Why TCP?

Q. 전송 계층에는 UDP, TCP 두개의 대표적인 프로토콜을 사용하는데 왜 나누고 어떤 경우에 TCP를 사용할까?

A. UDP는 빠른 데이터 송/수신을 위해서, TCP는 Reliable한 통신을 하기 위해서 사용한다.

Mechanism for Reliable Data Transfer

Sequence Number

  • 패킷의 순서를 정렬하기 위한 용도로 사용한다.
  • 송신자에서 수신자로 흘러가는 패킷에 숫자를 매기는 용도이다.

CheckSum

  • 전송되는 패킷 데이터 bit의 오류를 검증하기 위해 사용한다.
  • Error Detect 용도, FEC & CRC를 이용해서 에러를 찾고, 메꾸고, 유효성 검사를 한다.

Acknowledgement

  • 송신측에서 보낸 패킷을 수신측이 제대로 받은 경우 응답을 위해 사용한다.
  • 제대로 받지 못한 경우에 응답하는 방법은 Negative Acknowledgement (NACK)이다.

Timer

  • 송신측에서 보낸 패킷의 응답을 기다릴 때 사용하는 타이머이다.
  • Timer는 패킷을 보내는 순간 같이 시작되며 타이머가 만료되면 패킷을 재전송하거나 커넥션을 닫는 등 적절한 조치를 취한다.

TCP 프로토콜의 특징

1. Point to point

  • 송신/수신 측이 명확하게 정해져있다.
  • 일반적으로 서버-클라이언트 구조로 통신이 이뤄진다.

2. Full duplex data

  • 하나의 커넥션으로 양방향 통신이 이뤄진다.
  • 양쪽이 송/수신 둘다 한다.

3. Reliable, in-order byte stream

  • 믿을만하고, 순서가 지키져지는 byte stream으로 이뤄진다.
  • 일련의 byte를 세그먼트 단위로 통신한다.
  • bit를 보고 error control이 이뤄진다.

4. (receiver) Flow controlled

  • 수신측 패킷 상황을 보고 window size를 적절히 조절하여 보낸다.
  • 패킷이 너무 몰려서 패킷 유실이 발생하지 않도록한다.

5. (network) Congestion controlled

  • 네트워크의 상황을 보고 window size를 적절히 조절하여 패킷 유실이 발생하지 않도록 한다.
  • 네트워크 상황 계기판이 있는 것도 아닌데 어떻게 확인할까?
    -> 암시적으로 판단한다. 패킷유실이 일정 수치 이상으로 발생하다거나, 네트워크가 너무 느리게 간다거나 등

6. Connection-Oriented

  • 3-way handshake를 통해 연결지향 통신을 한다.
  • 연결 지향은 BUFFER를 이용하여 이뤄진다. 데이터를 송/수신 하기 전에 송/수신 용 Buffer를 먼저 할당한다.

Sender, Reciver측 Buffer 개념도

Flow Control, Error Control

  • 데이터 재전송은 ARQ(Automatic Repeat Request)를 통해 이뤄진다.
  • Error Check(Checksum, CRC)를 통해 에러를 발견하고 재전송을 요청한다. -> Reliable한 통신으로 만든다.
  • Flow Control은 ACK의 수신여부로 결정된다. 보낸 패킷의 응답이 오지 않는다면 수신측 or Network의 문제로 판단하고 window size를 조절하게 된다.
  • ACK는 패킷을 받을 때마다 보내지 않고 Cumulative한 방식으로 보내거나, Piggybacking 방식으로 보낸다.
    • Cumulative (누적방식) : 수신된 세그먼트의 누적 결과에 대해 ACK를 보낸다. 하나하나 보내지 않고 세그먼트 여러개에 대한 누적 결과에 대해 응답함
      만약 수신/송신 데이터의 양이 1:1이 아니라면 ACK만 쌩으로 보내야할 수 있는데 이를 방지하고자 사용된다.
    • PiggyBacking : 전송할 데이터 패킷에 Ack를 포함해서 같이 보내는 방식이다. (돼지 위에 얹힘)

TCP Segment 구조

TCP Segment

TCP Header

  • SRC port number, DST port number (4계층 주소 port number)
  • Sequence number
    • 보낼 데이터의 시작 byte 주소로 지정된다.
    • Segment의 번호랑은 다르다.
    • 3-way handshake를 위한 세그먼트의 경우 SEQ는 0 ~ (2^31 - 1) 사이의 랜덤값이 초기값으로 설정된다. (상대적 0을 의미)
  • Acknowledgement number
    • 받은 데이터의 응답값으로 다음에 받을 data의 시작 byte주소로 지정된다.
      -> 받은 데이터의 seq num + data 길이
    • 3-way handshake를 위한 세그먼트의 경우 ACK는 SEQ + 1로 설정된다.
  •  HLEN : 세그먼트 패킷의 Header 길이이다.
  • Reserved : 예약된 공간, 즉 아직 안쓰는 공간이다.
  • URG, ACK, PSH, RST, SYN, FIN (특정 기능을 표시하는 1 bit들이다)
    • urgent, ack, push, reset, synchronize, finish
  • Window Size : Flow Control, Congestion Control을 위한 Window size
  • Check sum : 에러 Detection을 위한 체크섬 비트
  • Urgent Pointer : 위에 URG 비트가 켜지면 사용되는 용도이다.

6개 비트 설명

SYN

  • Connection을 initiate할 때 사용한다.

ACK

  • 수신 데이터의 응답 ACK의 유효성을 표시해준다. 유효하면 1

FIN

  • 연결을 종료할때 사용한다.

RST

  • 에러가 발생하면 연결을 중단하고 재수립한다.

PSH

  • 전송받은 Host가 데이터들을 Application으로 올리라는 용도로 사용한다.
  • 버퍼에 쌓아둔 데이터를 빨리 읽어들여서 상위 계층으로 올리라는 것이다.
  • 해당 애플리케이션이 OS상에서 후순위로 밀려서 일을 천천히 하고 있을 때 전송이 느려질 경우 사용될 수 있다.
  • 전달받은 데이터를 Application 계층으로 올려 보내기전에 버퍼가 가득찰 때까지 모으고 올라가는 것을 방지한다.

URG, URG Pointer

  • 현재 사용하지 않는다. -> TCP의 in-order 정책에 어긋나는 기능이기 때문 
  • URG pointer는 보내는 세그먼트의 데이터의 0번 byte부터 ~ 특정 byte까지 긴급하다고 알리는 역활을 한다.
    • urg pointer가 5라면 0~5byte는 긴급 byte로 버퍼에 쌓여있는 byte를 무시하고 처리하도록 한다.

TCP Connection

2-way handshake의 문제점

  • 클라이언트가 Connection 요청을 보내고 서버가 응답을 한다. 이때 서버가 요청을 보고 buffer를 세팅하여 연결을 수립하고 응답 패킷을 보냈을 때 해당 패킷이 손실되면 클라이언트는 서버가 응답을 보내지 않았다고 판단하고 Timer가 만료되면 다시 연결요청을 재전송하게 된다. 서버는 수립한 커넥션을 둔 채 또 새로운 커넥션을 만들게 된다. -> 자원낭비를 유발한다.

3-way handshake 해결책

  • 서버가 응답을 보내면 클라이언트가 서버의 응답을 확인하고 커넥션을 수립하고, 다시 응답을 보낸다. 서버는 자신이 보낸 응답에 대한 응답을 받고 커넥션을 수립한다.

3-way handshake

연결수립을 위한 3-way handshake 예시

클라이언트 -> 서버 (SYN Bit = 1)

  • 클라이언트 -> 서버로 처음 연결을 시작할 때 SYN (synchronize) bit를 활성화한다.
  • client측 initial 패킷은 ACK가 없고 따라서 Ack Bit도 비활성화 되어있다. 이후 모든 패킷의 ACK bit는 활성화된다.
    (그림 오류, A는 없는게 맞다)
  • SEQ number 는 0 ~ 2^32 -1 사이의 랜덤 수로 설정한다. (해당 수가 상대적 0번이 된다, 보내는 데이터의 시작 주소의 기준)

서버 -> 클라이언트 (SYN Bit = 1, ACK Bit = 1)

  • 서버 -> 클라이언트로 처음 연결을 시작할 때 SYN (synchronize) bit를 활성화한다.
  • 클라이언트에서 보낸 패킷의 응답으로 ACK number는 받은 패킷의 SEQ number + 1을 ACK로 설정하여 보낸다.
  • SEQ number 는 0 ~ 2^32 -1 사이의 랜덤 수로 설정한다. (해당 수가 상대적 0번이 된다)

클라이언트 -> 서버 (ACK Bit = 1)

  • 서버에서 보낸 응답을 확인하므로서 서버가 LIVE 하다는 것을 확신하고 수신/송신 용 BUFFER를 ESTABLISH 한다.
  • 응답에 대한 응답으로 받은 패킷의 SEQ number + 1로 ACK를 세팅하고 보낸다.

서버

  • 클라이언트로부터 응답을 받은 서버는 클라이언트가 제대로 연결을 했다는 것을 확인하고 수신/송신 용 BUFFER를 ESTABLISH 한다.
세그먼트 전송 예시

클라이언트 -> 서버 (ACK bit = 1, PSH bit = 1)

  • 클라이언트가 서버에 데이터를 담은 패킷을 보낸다.
  • SEQ가 8001이란 것은 전달할 DATA의 시작 Byte 주소가 8001이란 것이다.
  • DATA를 보면 전달하는 데이터의 길이는 1000임을 알 수 있다.
  • ACK는 이전에 받은 패킷의 SEQ + 1로 세팅해서 전달한다.

클라이언트 -> 서버 (ACK bit = 1, PSH bit = 1)

  • 한번 더 보낸다. 
  • DATA는 9001 ~ 10000을 보낸다. 시작 Byte는 9001이므로 SEQ도 9001이다.
  • PUSH가 활성화 되었으므로 수신측 서버는 버퍼에 있는 데이터를 쭉 읽어들여서 애플리케이션 계층으로 올리게 된다.

서버 -> 클라이언트 (ACK bit = 1)

  • piggybacking 이다. (데이터 + ACK 조합)
  • cumulative ACK이다. (수신받은 패킷을 누적하여 응답함)
  • 전달하는 DATA가 15001 ~ 17000으로 시작하는 Data Byte가 15001이므로 SEQ도 15001이다.
  • ACK는 전달받은 데이터의 길이가 1000이고 시작 주소는 9001이였으므로 다음에 받을 byte 번호는 9001 + 1000로 10001이 된다. (다음에 받을 byte 주소)

클라이언트 -> 서버 (ACK bit = 1)

  • 그냥 쌩 ACK 세그먼트이다.
  • 데이터가 포함되지 않는 경우 SEQ는 보낼 데이터의 시작 Byte주소가 아닌 보냈던 데이터의 마지막 byte 주소가 된다.
  • 따라서 이전에 보낸 9001 ~ 10000 데이터의 마지막인 10000이 된다.
  • ACK는 상대방으로부터 받을 다음 Byte주소가 된다. 받은 SEQ + 데이터 길이이다.

TCP Connection Termination

4-way handshake 방식

클라이언트 -> 서버 (FIN = 1)

  • 종료를 원하므로 FIN Bit를 활성화해서 보낸다.

서버 -> 클라이언트

  • 서버는 FIN 요청을 받고 ACK를 보낸다.
  • 클라이언트에게 보내야할 패킷이 남아있다면 마저 보낸다.
  • 다보내고 난 후 클라이언트에게 FIN을 보내고 서버를 CLOSE 한다. Buffer가 할당해제된다.

클라이언트 -> 서버

  • 클라이언트는 FIN 요청을 받고 ACK를 보낸다.
  • 서버로부터 받아야할 패킷이 남아있을 수 있으므로 일정시간 기다린다. 이후 받을거 다 받고 CLOSE한다.
반응형
Comments
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday