4 minute read

개요

OSI 7계층안에서, 프로세스와 프로세스간의 통신을 담당하는 계층을 전송계층이라고 한다. 전송계층의 경우 송신측에서 데이터를 여러조각으로 쪼개는 세그맨테이션과 수신측에서 다시합치는 과정을 진행한다. 만약 데이터를 통으로 보냇을때 실패하면 다시 전송해야 하고, 이는 네트워크 트래픽 비용 증가로 이뤄진다. 데이터를 여러 세그먼트로 나눔으로써, 오류발생시 재전송되는 비용을 줄여 효율성있고 신뢰성있는 통신을 도와준다.

TCP

전송계층의 전송제어 프로토콜 이다. 흐름제어, 오류제어, 혼잡제어의 전송제어를 통해 네트워크망의 사정에 맞춰 오류없이 순서대로 신뢰성있게 데이터를 전송할수 있도록 도와준다. TCP 통신은 단방향이 아니라 양방향으로 이루어지기때문에 하나의 패킷에 순서번호, 확인응답번호, 패킷을 모두 포함하여 효율성을 올리는데 이를 피기배깅 이라고 한다. TCP 패킷에는 프로세스의 포트정보, 순서번호, 확인응답번호, 체크섬, Flag 등이 있다.

UDP

  • 비연결형 비신뢰성 전송계층 프로토콜 이다.
  • 8비트의 고정헤더로 구성되어있다. 흐름제어, 오류제어, 혼잡제어 기능을 제공하지 않으며 여러 프로세스를 하나의 UDP가 서비스할수 없다. DNS나 스트리밍 구축시 많이 사용한다. UDP에서 패킷은 데이타그램 이라고 부른다.

흐름제어

수신자마다 세그먼트를 처리하는 속도가 다르기 때문에, 수신자의 패킷 처리 속도에 맞춰서 송신자에서 전송하는 기법이다. 수신 측은 자신이 처리할 수 있는 수신 윈도우 크기(rwnd)를 자신의 응답 헤더에 담아서 송신 측에게 전해주게 되고, 송신 측은 상대방에게 데이터를 보낼 때 이 윈도우 크기를 고려하여 수신측의 상황에 맞게 데이터를 전송한다. 그렇다면 수신측에서 송신측에 피드백할 rwnd를 어떻게 구할수 있을까?

수신측에서는 네트워크로부터 데이터를 받기 위한 버퍼와 현재 송신측에서 받은 마지막 데이터크기인 LastByteRcvd 와 송신측에서의 어플리케이션에서 처리완료한 데이터크기 LastByteRead 를 알고 있다. 이때 버퍼 오버플로우를 막기 위해 buffersize>=LastByteRcvd-LastByteRead 여야 하는데 이를 통해 현재 수신가능한 데이터의 크기 rwnd=buffersize-LastByteRcvd-LastByteRead 를 구하여 송신측에 피드백할수 있다. 이제 송신측에서 LastByteSent−LastByteAcked≤rwnd 를 통해 수신측에 데이터를 더보내도 될지 판단이 가능해진다.

그렇다면 A에서 B로만 데이터전송중인데, B의 버퍼가 가득차 A에 rwnd가 0이 되면 어떻게 될까? B에서는 A로 데이터 전송도 하지않고 ACK도 없기 때문에 A의 rwnd가 0에서 갱신이 안되는문제가 있다. 그래서 일단 1바이트씩 rwnd에 상관없이 일단 B로 보내도록 TCP가 설계되어있다. 만약 1바이트를 수신했다면 해당 데이터에 대한 ACK를 보낼때 새로운 rwnd를 보내줄수 있을것이다.

수신자가 피드백해준 rwnd (receiver window) 변수와 와 뒤에서공부할 혼잡 윈도우인 cwnd (Congestion window) 변수값을 고려해서 송신버퍼의 슬라이딩윈도우(송신 윈도우)의 크기가 정해진다.

순서 번호

세그먼트별로 부여되는 일련의 고유번호를 순서번호라 한다. 전송계층의 통신의 경우 한번에 모든데이터를 전송시키지 않고 세그맨테이션을 통해 순서번호를 부여한후 순서대로 전송한다. 순서번호 부여시 주의점이 하나 있는데, 순서 번호의 최댓값이 송신 윈도우 크기보다 커야 한다. 순서 번호를 지정할 때 최댓값 이후에 다시 0번으로 순서 번호를 지정하기 때문에 송신 윈도우의 크기가 더 클 경우 순서 번호가 겹치는 현상이 발생할수 있기 때문이다.

오류제어

수신측에서 받은 프레임이 손상되어서 송신측에 NACK를 보내거나, timeout으로 확인응답을 못보낸다면 송신측에서 해당 순서번호를 다시 보내주는 방식(SYN)으로 오류제어가 동작한다. 크게 3가지 방법이 있다.

  • Stop and Wait ARQ
    • 하나씩 보내고, 하나씩 까보면서 에러를 확인한다.
    • 느리다.
  • Go back N ARQ
    • 수신측에서는 가장 최근에 받은 순서번호 다음번호만 받는다.
      • 만약 다른 순서번호가 오면 drop하고 다음번호에 대한 ACK를 보낸다.
    • 송신측에서는 시간이 지나도 수신측으로 응답이 없다면 타임아웃 확인된 마지막 프레임 이후로 모든 프레임을 전송한다.
    • 수신윈도우는 한번에 세그먼트를 하나씩 처리하여 ACK를 보낸다.
  • SR(Selective-Reject) ARQ
    • 일단 수신측에 순서가 안맞더라도 버퍼에 저장한후 ACK를 보낸다. (재전송한 데이터때문에 프레임의 순서가 안맞을수 있기 때문에 버퍼를 둔다)
    • 송신측에서는 모든 TCP 세그먼트에 대해 타이머를 걸어, timeout된 친구들을 재전송한다.
    • SR은 수신 슬라이딩 윈도우 (수신윈도우)의 size가 sequence number의 개수의 절반보다 이하여야한다.
      • 왜냐하면 window는 원형큐이므로, 윈도우를 갱신하다면 첫번째 순서번호로 돌아올수 있다!
      • 그렇게 되면 이 순서번호가 옛날에 받았던것인지 새로운것인지 구분못한다.
      • 수신윈도우가 0 1 2 3 0 1 2 상황에서 0인 패킷이 왔다가 해보자
      • 왜냐하면 go back N의 경우 순서대로 쌓기 때문에 문제가 없지만
      • SR은 수신윈도우에 0을 인식하므로 이 0이 옜날 0인지 지금 0인지 알수 없다.
      • window size <= (sequence number)/2 보다 작게 가져가면 문제가 안발생한다.

혼잡제어

송신쪽에서 네트워크 환경을 고려해서 속도를 조절하는것이다. 혼잡상황은 어떻게 판단할까 송신후 timeout 타이머안에 ack가 오지 않거나, 3번의 중복 ack가 오게 되면 혼잡이라고 판단한다. 수신측에서도 ack를 보낸다음 timeout 타이머안에 새로운 순서번호의 패킷이 오지 않으면 또 ack를 보내게 된다. 이게 3번이상 발생하면 송신측에서 3번의 중복 ack를 받게 된다. 이를 위해 혼잡윈도우(cwnd) 변수를 rwnd 변수와 별도로 관리를 한다. 크게 두가지 방법이 있다.

  • tahoe (slowStart + AIMD + fast Retransmit)
    • slow-start(2배씩 증가시키다가 혼잡시 1로 줄인다)와 threshold부터 AIMD(1씩증가시키다 혼잡시 1/2로 줄이기)방식을 사용한다.
    • 혼잡상황 (3 duplicated ack, timeout) 이 되면 혼잡상황때의 데이터를 기반으로 threshold를 설정한후, 1로줄인다음 다시 slow-start + AIMD로 혼잡윈도우를 증가시킨다.
    • 3 duplicated ack 의 경우 timeout과 상관없이 패킷을 재전송 한다(빠른 재전송)
    • Tahoe의 단점은 초반의 Slow Start 구간에서 윈도우 크기를 키울때 너무 오래 걸린다. 혼잡 상황이 발생했을 때 다시 윈도우 크기를 1부터 키워나가야 한다는 점이 낭비가 될수 있다.
  • reno (tahoe + fast recovery)
    • 3 ACK Duplicated와 Timeout을 구분한다.
    • 3 ACK Duplicated 발생시 1이 아니라 반타작 낸후 AIMD로 처리하는데 이를 빠른 회복 기법이라 한다.
  • newreno
    • 연속적인 loss(중복 ack)가 발생하면 window size를 계속해서 절반으로 줄이는 사태가 발생할 수 있다.
    • 따라서 혼잡상황이발생하면 cwnd를반으로 줄이고, fast recovery 상태를 지금까지 보냈던 패킷들에 대한 ACK 가 올때까지 계속 유지한다. 그 전까지는 혼잡이 또 발생하더라고 반으로 또 줄이지 않는다.

3 way handshake

  • 클라이언트는 첫 번째 세그먼트로 SYN 플래그가 1로 설정되어있고 임의의 값을 순서번호 n으로 설정한 SYN 세그먼트를 전송한다. SYN_SENT 상태
  • 서버가 SYN 을 수신후 Listen에서 SYN_RCVD 상태로 전환된다.
  • 서버는 두번째 세그먼트로서 SYN+ACK 플래그가 1로 설정되어있고 임의의 값 m 순서번호로 설정하고 ACK 순서번호를 n+1로 세그먼트를 전송한다.
  • 클라이언트는 ESTABLISHED 상태로 전환 ACK 순서번호 m+1 세그먼트 서버로 전송
  • 서버는 ESTABLISHED 상태로 전환

4 way handshake

  1. 클라이언트가 연결을 종료하겠다는 FIN Flag를 전송한다.
  2. 서버에서는 FIN 패킷을 정상적으로 받았다는 ACK를 클라이언트에 전송해준다. 그 후 서버는 CLOSE-WAIT 상태로 빠져든다.
  3. 연결을 종료한 후 서버는 클라이언트에게 FIN Flag를 전송해준다.
  4. 서버로부터 전송된 FIN Flag를 받은 클라이언트는 확인을 알리는 ACK를 서버로 전송한 후, 일정 시간동안 TIME-WAIT 상태에 빠지게 된다.
  5. 클라이언트로 부터 ACK를 받은 서버는 소켓을 Close하고 두 TCP간의 세션이 종료된다.
  6. TIME-WAIT에 빠진 클라이언트는 서버로 부터 FIN을 수신하더라도, 일정시간동안 세션을 유지하며 도착하지 않은 패킷을 기다린다.

체크섬

  • 세그먼트의 오류를 감지 하기 위해 checksum을 사용한다.
  • 체크섬 생성과정
    • psuedo header 생성 (source, dest, TCP+header+payload 바이트수, 프로토콜)
    • 16비트로 쪼개서 다 더한다. 도중에 캐리가 발생하면 모두 다시 1의 자리에서 더해준다.
    • 1의 보수를 취하면 완성
  • 헤더의 체크섬과 새로 계산된 체크섬이 다르면 재전송 요청

Leave a comment