Sequence Number

TCP(1)

2023. 11. 21. 13:25
728x90
TCP(1)

TCP

TCP 란 연결지향형 프로토콜이며, 다음과 같은 특징이 있다.

  1. point-to-point: 소켓과 소켓 간의 연결 (한쌍의 소켓 간의 연결이다)
  2. reliable, in-order byte stream : 신뢰성 및 순서 보장
  3. pipelined : 여러 데이터를 한번에 보낼수 있다.
  4. full duplex data: 송신자이자 수신자가 될수 있다.
  5. connection oriented : handshaking 을 연결단계에 한다.
  6. flow controlled: 상대방의 컴퓨터 성능에 맞춰 segment를 보낸다.
  7. congestion controll: 네트워크 상태에 따라 보내는 속도를 조절한다.


TCP 세그먼트 구조

IMG_E73C97BC5FAC-1

위 사진은 TCP 세그먼트 구조를 나타낸다.


순서 번호 (sequence number)

순서번호는 특정 세그먼트의 첫번째 바이트 이다. 예를 들어, 첫 번째 세그먼트가 100바이트 크기를 가지고 시작 순서 번호가 0이라면, 이 세그먼트는 0번 바이트부터 99번 바이트까지의 데이터를 포함한다. 따라서 다음 세그먼트의 시작 순서 번호는 100이 된다.


확인 응답 번호 (acknowledgement number)

확인 응답 번호는 다음으로 기대하는 바이트 이다. 만약 ACK#100 이라면, 나는 sequence number 가 99 번인것까지는 모두 정상적으로 받았고 이제 sequence number가 100번인 데이터를 받기를 기대한다 라는 의미이다.


Window

image-20231031103506466

 

TCP 연결을 하게되면 송신 수신 시스템 모두 Send Buffer 와 Rcv Buffer 를 가지게 된다.

이때 TCP 프로토콜은 애플리케이션 계층으로부터 받은 데이터를 Send Buffer에 넣은후 수신시스템인 B의 Rcv Buffer에 전송하게 된다.

애플리케이션 계층은 TCP 의 전송속도를 고려하여 소켓에 메세지를 보내지 않는다. 즉 Send Buffer엔 TCP 프로토콜에 의해 보내지는 데이터보다 더 많은 데이터가 쌓여있다.

Window란 Send Buffer에서 TCP프로토콜이 한번에 보낼수 있는 데이터의 양이다.

즉 Window의 크기가 1000byte 라면 TCP 프로토콜은 한번에 1000byte의 데이터를 TCP가 연결된 상대방에게 보낼수 있는 것이다.


TCP 커넥션에서 타이머 및 Send Buffer Rcv Buffer의 상세한 동작과정은 컴퓨터 네트워크 강의 해당 강의 38:00 부터 보면된다.

위 강의를 기반으로 TCP 연결에서의 버퍼 동작과정을 간단하게 정리를 하자면

  • Send Buffer 는 결국 재전송을 위한 버퍼이다. base send에 타이머가 물려있으며, 전송해야하는 데이터에 대한 ACK 응답을 받으면 타이머를 이동시킨다.
  • Rcv Buffer 는 in-order 를 위한 버퍼이다. sequence number를 기반으로 데이터가 순서에 맞춰 잘 들어 왔는지 확인한다.
  • A,B 모두 데이터를 보내고 받을수 있다. 실제 TCP 동작에선 Send Buffer에서 데이터를 보낼때 해당 데이터의 헤더의acknowledgement number에 ACK 응답을 포함한다. (sequence number에는 보내는 데이터의 sequence number가 들어간다.)


Timer 한계 극복

Timer 라는건 Send Buffer의 base send(보내야하는 맨앞 데이터)를 가리키고있다.

해당 데이터에 대한 ACK응답이 도착하면 Send Buffer에서 해당 데이터를 지운다. 만약 데이터가 중간에 유실되었다고 가정해보면, Timer의 timeout 전까지는 재전송을 하지 않으며, 이는 생각보다 비효율 적이다.

Timer의 timeout은 기본적으로 평균 rtt + margin 정도의 시간을 가지는데 이는 생각보다 긴 시간이다.

이러한 문제점을 해결하기위해 fast retransmit(빠른 재전송) 을 사용한다.


image-20231031111148654

위 그림과 같이 윈도우의 크기가 400바이트 이며, 각각의 segment는 100바이트라고 가정을 해보자.

이때 sequence number가 100인 데이터가 전송되는 과정에서 유실되었다고 하면, 수신 시스템에서의 Rcv Buffer는 위와 같이 sequence number가 100인 segment를 제외한 나머지 segment만 있을 것이다.

이때 수신 시스템에서는 ACK 응답을 보내야하는데, 아래와 같이 보낸다.

  • sequence number가 0인 데이터에 대해서는 ACK#100 (0~99까지는 잘받았으니 이제 받아야하는게 sequence number가 100인 data야~)
  • sequence number가 200인데이터에 대해서도 ACK#100 이 전송된다. 왜냐하면 TCP 프로토콜은 순서를 보장해야한다. 따라서 Rev Buffer는 아직 100번째 segment가 오지 않았기때문에 ACK#100을 응답으로 전송한다.
  • sequence number가 300 인 데이터에 대해서도 위와같은 이유로 ACK#100이 응답으로 전송된다.


위과정에서 결국 sequence number가 100인 데이터가 재전송이 되겠지만, timeout이 걸릴때까지 대기해야한다. 따라서 TCP는 3개의 중복 ACK를 수신할 때, 타이머에 관계없이 세그먼트를 재전송하는 fast retransmit을 사용한다. 이때 주의해야 하는점은 3개의 중복 ACK가 의미하는건 알맞은 응답에 대한 ACK 를 제외한 3개의 중복 ACK를 받아야 재전송한다는 의미이다.

IMG_29D4C0848EAE-1

위 사진처럼 실제론 4개의 응답을 받아야 fast retransmit에 의해 segment를 재전송 한다.

즉 Timeout 이 지나지 않더라도, fast retransmit(빠른 재전송) 을 사용하게되면 더 효율적으로 TCP 통신을 할수 있다.

728x90

'네트워크' 카테고리의 다른 글

RDT(Reliable Data Transfer)  (1) 2023.11.21
Multiplexing, deMultiplexing  (0) 2023.10.25
소켓  (0) 2023.10.23
DNS  (0) 2023.10.19
HTTP1/HTTP2/HTTP3  (0) 2023.10.19

RDT(Reliable Data Transfer)

2023. 11. 21. 13:16
728x90
rdt 원리

3.4 rdt 원리

TCP 프로토콜은 신뢰적인 데이터 전송 rdt(reliable data transfer) 를 지원한다.

rdt 를 보장하기 위해 필요한건 다음과 같으며 순서대로 설명해보겠다.


  1. error detection
  2. feedback
  3. sequence number
  4. timer


TCP 의 세그먼트는 사실 트랜스포트 계층 이외도 전송계층, 링크계층, 물리계층을 모두 타고 이동하여 상대방에게 전송된다.

즉 트랜스포트 계층 이외 계층을 통해 데이터가 전송될때도 TCP 의 rdt 가 지켜지기 위해 TCP는 여러 헤더를 사용한다.


데이터는 여러 라우터를 거쳐 상대의 종단 시스템에 도착할 것이다. 이때 발생할수 있는 문제(rdt 를 위배할수있는 문제)는 2가지 정도 된다.

  1. 데이터 이동중 에러 발생 (데이터는 결국 010101 이런식으로 보내질텐데, 데이터가 손상될수 있다.)
  2. 데이터 Loss (앞서배운 큐잉지연 등에 의해 데이터가 손실될수 있다.)

rdt를 위배할수 있는 위 2가지 사항을 극복하면 TCP 프로토콜은 rdt를 보장할수 있을 것이다.


1. error detection

우리가 수신시스템으로 보내는 데이터가 여러 라우터를 거치는 와중에 데이터에 에러가 발생할 가능성이 있다.

TCP 는 기본적으로 error detection 을 보장한다. 헤더에 checksum 필드를 추가하여 해당 데이터에 이상 유무를 수신단에서 확인할수 있게 한다.


2. feedback

수신 시스템에서 체크섬 필드를 통해 데이터의 이상유무를 확인했을때 해당 데이터에 이상이 있다면 송신 시스템으로 부터 데이터를 다시 전송받아야한다.

위와 같은 매커니즘을 사용하려면, 송신 시스템은 수신시스템으로부터 이상없는 데이터를 받았는지에 대한 feedback 이 필요할 것이다.

이때 사용하는 것이 ACK(positive acknowledgment) 와 NAK(negative acknowledgment) 이다.


ACK, 와 NAK 는 일종의 피드백이다. 수신자 축에서 받은 데이터에 대해 오류가 있으면 송신자 측으로 NAK 응답을 보내고, 오류가 없다면 ACK 응답을 송신자 측으로 보낸다.


❗️ACK 손상 가능성

위 설명대로 일종의 피드백 형태인 ACK 와 NAK 를 사용하면 데이터가 이동중 에러가 발생했을 상황을 극복할수 있을것 같다.

하지만 우린 ACK 또는 NAK 패킷이 손상가능하다라는 가능성을 고려해야한다.

즉 수신 시스템이 이상이 있는 데이터를 받아 송신 시스템에게 NAK 응답을 했는데, 만약 NAK 응답자체가 송신시스템으로 가는 도중에 손상이 발생한다면?

위와같은 상황을 해결하기 위해 tcp 프로토콜은 sequence number를 사용한다.


3. sequence number

수신자측은 데이터를 받을때 송신자 측에게 ACK 또는 NAK 응답을 반드시 보낸다.

위와같은 ACK응답이 손상되었을때 재전송 을 해결방안으로 생각한 사람이 있을수도 있다.

ACK응답이 오지 않으면 그외의 경우는 모두 재전송을 한다고 가정했을때, 문제가 발생할수 있는 경우는 아래와 같다.


수신자 측에서 오류가 없는 데이터 A 를 받았다고 가정한다.

그후 수신자는 송신자에게 데이터 A에 대한 ACK 응답을 할것이다.

하지만 이 ACK 응답이 가는도중 데이터에 에러가 발생하여 송신자 측에 응답이 도착했을땐 ACK 인지 NAK인지 판단할수 없다.

따라서 송신시스템은 데이터 A를 수신시스템에게 재전송 할 것이다.

데이터 A 가 수신시스템에게 왔다, 수신시스템은 데이터 A가 재전송이 된 데이터인지, 새로운 데이터인지 판단할수 없다.


위 가정에서 보면 결국 수신시스템은 수신한 데이터가 재전송을 위한 데이터인지, 새로운 데이터인지 판단해야한다.

이런 상황을 타개하기위해 sequence number 를 사용하는 것이다.

sequence number 는 송신자 측에서 보내는 세그먼트에 고유한 순차 번호를 부여하는 것이다.

수신자 측에서는 순차 번호를 통해, 받은 데이터가 중복된 데이터인지 새로운 데이터 인지 확인할수 있다.


수신자 측에서 오류가 없는 데이터 A (헤더에 순차번호가 0번인) 를 받았다고 가정한다.

그후 수신자는 송신자에게 데이터 A에 대한 ACK 응답을 할것이다.

하지만 이 ACK 응답이 가는도중 데이터에 에러가 발생하여 송신자 측에 응답이 도착했을땐 ACK 인지 NAK인지 판단할수 없다.

따라서 송신시스템은 데이터 A를 수신시스템에게 재전송 할 것이다.

데이터 A 가(헤더에 순차번호가 0번인) 수신시스템에게 왔다, 수신시스템은 순차번호를 통해 해당 데이터가 재전송된 데이터 인지 확인할수 있으며 해당 데이터를 버린다.


sequence number 를 도입하는 순간 NAK 의 필요성이 사라진다. 만약 수신자 측에서 ACK, 또는 NAK 응답을 보낼때 수신자가 지금까지 받은 데이터의 sequence number 를 같이 보내준다면 NAK 응답이 필요없어 진다. 이를 acknowledgement number 라고 한다.

acknowledgement number 는 수신자가 다음에 기대하는 바이트의 순서번호를 나타낸다.

즉 마지막으로 성공적으로 받은 데이터 바이트의 순서번호에 1을 더한다.

<정상적인 데이터를 받았을 경우>

수신자 측에서 오류가 없는 데이터 A (헤더에 순차번호가 0번인) 를 받았다고 가정한다.

그후 수신자는 송신자에게 데이터 A에 대한 ACK#1 (순차번호가 0번인 것까지는 완벽하게 받았으니) 응답을 할것이다.

송신자 측에선 ACK#1 을 통해 그다음 데이터인 1번 데이터를 전송해야 하는것을 알수있다.


<비정상 적인 데이터를 받았을 경우>

수신자 측에서 오류가 있는 데이터 B (헤더에 순차번호가 1번인) 를 받았다고 가정한다.

그후 수신자는 송신자에게 데이터 B에 대한 재전송을 위해 ACK#1 (순차번호가 0번인 것까지는 완벽하게 받았으니) 응답을 할것이다.

송신자 측에선 ACK#1 을 통해 순차번호가 1번인 데이터 B를 재전송 해야한다는 것을 인지할수 있다.


 

4. timer

지금까지 본 error detection, feed back, sequence number 3가지를 사용하면 rdt를 지키기위해 트랜스포트 계층 외 계층에서 발생할수 있는 error 에 대한 해결방안은 모두 제시했다.

이제는 Loss 에 대한 해결책만을 확인하면 된다.

Loss 는 잘못된 응답이 오고 안오고를 떠나서 응답자체가 안오는 경우에 대해서는 어떻게 해결을 할것이냐? 에 대한 물음이다.

즉 송신자 측에서 데이터를 보냈는데 데이터가 가는도중에 패킷이 유실되든, 수신자측에서 받은 데이터에 대한 응답이 송신자측으로 가는 도중에 유실이 되든 사실 송신자 입장에선 응답이 안오는 같은 상황이다.

단순히 생각해봐도 해당 응답이 올때까지 무한정 대기할수는 없다. 따라서 우린 timer 를 사용한다.

timer를 사용하여 일정 시간이 지나도록 응답이 오지 않으면 재전송을 하게한다.

대기하는 시간은 일반적으로 rtt(round-trip-time) + margin 으로 잡는다.

참고로 segment 를 보낼때마다 rtt를 측정하여, 재전송 타이머를 동적으로 조절한다 (매번 네트워크 지연시간이 다르기 때문에 첫번째 rtt 를 계속해서 타이머로 설정하는데에는 무리가 있다).

또한 이 평균을 측정하는데 있어서 재전송 에 대해서는 포함하지 않는다.

728x90

'네트워크' 카테고리의 다른 글

TCP(1)  (1) 2023.11.21
Multiplexing, deMultiplexing  (0) 2023.10.25
소켓  (0) 2023.10.23
DNS  (0) 2023.10.19
HTTP1/HTTP2/HTTP3  (0) 2023.10.19

+ Recent posts