Fast Retransmit (빠른 재전송)

 

- 재전송 타이머 값이 종종 상대적으로 길어지므로, 손실된 패킷의 재전송 전에 지연시간이 커진다.

 

- 위의 상항을 해결하고자 중복 ACKs를 통해 손실된 세그먼트를 검출한다.

 

- 송신측에서 바로바로 여러 개의 세그먼트를 전송할 경우, 세그먼트가 손실되면 수신측에서는 중복 ACK를 보내게 되는데, 타임아웃 전에 송신측에서 중복 ACK3받게 되면 세그먼트를 즉시 전송한다. , 수신측이 기다리는 순서번호의 세그먼트보다 큰 순서번호의 세그먼트가 3개 도착할 경우를 의미한다.

 

[ ACK2 의 중복수신 3번 이후 3번 데이터 즉시 전송 ]


 

 

 

 

Flow Control

 

- TCP 송신자가 데이터를 너무 빠르게 또는 너무 많이 전송하여 수신버퍼가 오버플로우(Overflow)하는 것을 방지한다.

 

- TCP의 수신자는 수신버퍼(receive buffer)를 가지는데, 상위 계층으로 세그먼트를 보내는 애플리케이션 프로세스가 수신버퍼로부터 데이터를 읽는 속도가 느릴 수 있다.

 

- 목표 : 애플리케이션 프로세스의 읽는 속도 = 송신자가 데이터를 전송하는 속도

 

- , 흐름제어는 속도를 일치시키는 서비스이다.


 


 

- Receive Window(rwnd) : 수신버퍼의 가용 바이트 수로, 송신 윈도우 크기를 결정한다.


LastByteRcvd - LastByteRead <= RcvBuffer


[밑에서 수신 받은 번호 - 위로 올려 보낸 번호 = 수신했지만 상위계층으로 전송되지 않은 데이터들]


=> 항상 수신 버퍼보다 작아야한다. 초과하면 오버플로우 발생.


rwnd = RcvBuffer - (LastByteRcvd - LastByteRead)

    = RcvBuffer - (수신했지만 상위 계층으로 전송하지 않은 데이터들)




- 수신자는 TCP헤더에 수신버퍼안에 있는 여유공간(Receive Window, rwnd) 값을 포함함으로써 버퍼에 공간이 있음을 송신자에게 알린다.

 

- 수신버퍼의 크기는 소켓의 옵션을 통해 설정되는데 디폴트 값이 4096바이트이다.

 









 

 

TCP Overview

 

- 점대점(Point-to-Point) : 단일 송/수신자간의 통신   ex) 일대일 통신, Unicast 전송

  • Unicast : 고유 주소로 식별된 하나의 네트워크 목적지에 메시지를 전송하는 방식
  • Broadcast : 송신 가능한 모든 목적지에 동일한 데이터를 전송
  • Multicast : 특별한 주소 지정 방식을 통해 정해진 여러 목적지로 데이터를 전송
  • 호스트가 무수히 많은 경우, Unicast로 데이터를 전송하면, 각각의 네트워크 연결마다 호스트의 컴퓨팅 리소스(자원)을 소비할 뿐 아니라 각각 다른 네트워크 대역폭을 필요로 하기 때문에 전송 비용이 많이 든다는 단점이 있다.

 

- 파이프라인(Pipeline) : TCP의 혼잡 제어 및 흐름 제어가 윈도우 크기(Window size)를 결정한다.

  • Window size : ACK받지 않은 데이터 중 최대 송신가능한 바이트 수, 수신자가 한 번에 버퍼링할 수 있는 최대 데이터 크기
  • Sliding Window : 두 개의 네트워크 호스트 간의 패킷의 흐름을 제어하기 위한 방법으로, TCP 프로토콜은 데이터의 전달을 보증해야 하므로 패킷 하나 하나가 정상적으로 전달되었음을 알리는 확인 신호(Acknowledgement, ACK)를 수신자가 송신자에게 보내야 한다.
  • 패킷에 오류가 생겼을 경우, 송신측에서 해당 패킷을 재전송해야 하는데 이 때 Sliding WindowWindow Size(메모리 버퍼의 일정 영역)에 포함되는 모든 패킷을 전송하고, 패킷의 전달이 확인되는 대로 이 Window를 옆으로 옮김(Sliding)으로써 그 다음 패킷들을 전송할 준비를 한다.

 

- 전이중성 데이터(Full-duplex Data) : 같은 연결 상에서 양방향 데이터 흐름

 

- 최대 세그먼트 크기 (Maximum Segment Size, MSS)

  • 헤더를 제외하고 TCP가 실을 수 있는 최대 데이터 크기
  • 기본값은 IPv4 -> 536 Byte, IPv6 -> 1220 Byte이다
  • 최대 전송 단위(MTU)에 의해 값이 결정되며, MSS값은 헤더의 MSS 옵션 필드에 저장된다.
  • 연결에 참여하는 두 장비가 서로 다른 MSS값을 갖을 수도 있다.

 

- 최대 전송 단위(Maximum Transmission Unit, MTU)

  • 데이터 링크(2계층) 또는 네트워크(3계층)에서 하나의 프레임 또는 패킷에 담아 운반할 수 있는 헤더를 포함한 최대 데이터 크기
  • 최소 권고값은 2계층 기준 1500Byte이며, 3계층 기준 IPv4MSS 크기에서 40byte(IP헤더+TCP헤더)를 추가한 576Byte이고, IPv61280Byte이다.
  • 실제로는 최대 65,646바이트 범위까지 생성가능하다.

 

- MTUIP 기반의 정보인 반면, MSSTCP 기반의 정보이다.

 

- TCP는 연결지향형으로 제어 메시지들의 교환(Handshaking)이 이루어진다. 핸드쉐이킹을 통해 데이터 교환 전에 송신자 및 수신자의 상태를 초기화한다.

 

- 흐름 제어(Flow Control) : 수신자의 속도에 맞춰서 송신자가 데이터를 보낸다.

 

 


 

TCP Segment

 


- Source port number : 출발지 포트 번호

 

- Destination port number : 도착지 포트 번호

 

- Sequence number : 순서번호(Seq#), 세그먼트에서 첫 번째 바이트의 바이트 스트림 번호값이 저장된다.

 

- Response number : 확인응답(누적된 ACK)번호로, 상대방으로부터 받아야할 다음 바이트의 순서번호값이 저장된다.

ex) ACK100이 들어있으면 99번 데이터까지 잘 받았음을 의미한다.

 

- Header length : 헤더의 길이로, Option이 없으면 헤더값에 5개의 비트값이 들어간다. 그러나 일반적으로 32비트이다.

 

- Reservation : 나중에 다시 설명

 

- Control flag 

  • 구체적으로 flag순서는 URG, PSH, RST, SYN, FIN이고 각각 1비트로 표현되는 값이 저장된다.

  • 중요한 부분만 집어보자면, 통신과정에서 연결 설정이 필요할 때 RST, SYN, FIN을 사용한다

  • RST는 연결을 재설정(Reset)할 때 연결을 종료하기 위한 비트값으로 비정상적인 세션 연결 끊기가 해다된다

  • 연결 요청 시에는 SYN=1 의 비트값을 넣어 세그먼트를 전송한다.

  • 연결 해제할 때는 FIN=1 의 비트값을 저장하여 세그먼트를 전송한다.

 

- Window : 수신측의 윈도우 크기(Window size), 받을 수 있는 최대 데이터 크기값이 저장되어 있다.

 

- TCP Checksum : 검사합(Checksum)이 저장되는 데, 체크섬값이란 세그먼트의 합에 1의 보수를 취한 값을 말하며, 수신측에서 체크섬과 세그먼트의 실제 데이터를 더한 결과를 통해 오류를 검출한다.

 

- Emergency Data point : 생략

 

- Option : 변수의 길이로 설명은 생략.

 

- Data : 헤더를 제외한 실제 세그먼트에 들어있는 데이터의 크기로 MSS에 의해 제한되어진다.

 

 

 

TCP Round Trip Time, Timeout

 

- TCP는 신뢰적인 데이터 전송(RDT)처럼 세그먼트의 손실을 발견하기 위해 타임아웃/재전송 메커니즘을 사용한다. 이 때, 송신측에서 데이터를 전송한 후, ACK받기까지 걸린 시간을 RTT(Rount Trip Time)이라 표현한다.

 

- 타임아웃(timeout) 주기는 RTT보다 길어야 한다. 너무 짧으면 타임아웃이 자주 발생하여 세그먼트의 불필요한 재전송이 발생하므로 링크를 비효율적으로 사용하게 된다. 반대로 너무 길게 되면, 세그먼트의 손실에 대한 느린 대응으로 회복이 비효율적이게 된다.

 

- SampleRTT : 세그먼트가 송신된 시간부터 ACK 받기까지 측정된 시간으로, 재전송한 세그먼트는 무시한다. 값은 네트워크 부하에 따라 가변적이다.

 

- 현재 SampleRTT 값이 아닌 최근의 값들의 평균값으로 추정한다.

 

- 추정RTT : EstimatedRTT = (1-a) * EstimatedRTT + a * SampleRTT

일반적으로 a=0.125이고, 지수적 가중 이동 평균(EWMA)방식으로 과거 샘플들의 영향이 지수적으로 감소한다. a가 높을수록 SampleRTT에 더 영향을 준다.

 

- DevRTT : RTT 변화율로, SampleRTTEstimatedRTT의 편차값이다. , 현재 RTT값이 추정 RTT값으로부터 얼마나 벗어났는가에 대한 정보이다.

 

- 재전송 타임아웃 주기 (Timeout Interval) = EstimatedRTT + 4 * DevRTT

 

- 타임아웃나서 세그먼트를 재전송하게 되면, 재전송한 세그먼트에 대한 타이머가 시작된다.

 

 

 


TCPRDT

 

- TCP는 비신뢰적인 인터넷 네트워크 계층(IP서비스)의 상위 계층에서 신뢰적인 데이터 전달(Reliable Data Transfer, RDT) 서비스를 제공한다.

 

- 파이프라인되는 세그먼트 (ACK의 응답이 없어도 다수의 세그먼트를 전송가능)

 

- 누적된 ACKs

 

- 단 하나의 재전송 타이머

 

- 재전송은 타임아웃이 되거나, 중복 ACKs를 수신했을 경우 발생한다.

 

- “간소화된 TCP 송신자는 중복 ACKs를 무시하고 흐름제어 및 혼잡제어를 무시한다.

 



 

 

TCP 송신자의 3가지 상황(Sender Events)

 

- 상위 계층으로부터 수신된 데이터 : 데이터를 받았으므로 상위 계층으로부터 데이터 전송 요청이 오게 된다.

  • 순서번호(Seq#)를 가진 세그먼트 생성 (Seq# : 세그먼트의 첫 번째 바이트의 바이트 스트림 번호)

  • 타이머가 실행되지 않고 있으면 타이머를 시작한다.

  • 타이머의 만료주기는 Timout Interval 로 계산한다.

 

- 타임아웃 : 타임아웃에 의해 세그먼트가 재전송되고, 전송했으나 ACK 받지 않은 가장 오래된 세그먼트에 대해 타이머가 다시 시작한다.

 

- ACK를 수신한 경우 : 이전에 ACK받지 않은 세그먼트의 ACK 이면, 해당 세그먼트를 ACK 응답된 세그먼트로 표시한다. , 윈도우 크기를 조정한다. 아직 ACK받지 못한 세그먼트들이 존재한다면 타이머를 시작한다.

 


 

NextSeqNum = InitialSeqNum

SendBase = InitialSeqNum   //송신했으나 ACK되지 않은 가장 오래된 순서 번호

 

loop(forever) {

switch(event) {

event : data received from application above // 상위 계층으로부터 수신된 데이터

create TCP segment with sequence number NextSeqNum // 다음 순서번호를 가진 TCP 세그먼트 생성

if(timer currently not running) { // 아직 타이머가 시작하지 않았다면

    start timer //타이머 시작

}

pass segment to IP // 생성한 세그먼트 목적지 IP주소로 전송

NextSeqNum = NextSeqNum + length(data) // 전송할 세그먼트의 순서번호 변경


event : timer timeout // 타임아웃

retransmit not-yet-acknowledged segment with smallest sequence number

start timer

 

event : ACK received, with ACK field value of y //y번의 ACK를 수신한 경우

if (y > SendBase) { // 누적된 ACK가 도착한 경우(새 데이터가 온 경우)

SendBase = y;

if (there are currently not-yet-acknowledged segments) { //아직 ACK받지 않은 데이터가 남은 경우

    start timer //타이머 시작

}

}

}

}



 

- 세 가지 상황에 대한 재전송 시나리오

 

 

 





TCP 수신자의 4가지 상황(Receiver Events)

 

<문제가 없는 상황>

- 기다리는 순서번호의 세그먼트가 도착. , 이전의 데이터들은 모두 ACK받은 경우

 => 지연된 ACK 발생. 다음 세그먼트를 위한 500msACK타이머가 설정되고, 시간 안에 다음 세그먼트가 오지 않을 경우 ACK를 전송한다.

 

[ 오른쪽이 지연된 ACK의 모습 ]


 

- 기다리는 순서번호의 세그먼트가 도착. 하나의 다른 세그먼트가 ACK 지연시간(500ms)안에 수신된 경우

 => 하나의 누적 ACK를 송신측으로 즉시 전송한다.

 



<문제가 있는 상황>

- 기다리는 것보다 높은 순서번호를 가진 세그먼트가 도착. , 송신측에서 여러 개의 세그먼트를 전송한 후 중간 세그먼트가 손실된 경우 => 즉시 기다리는 바이트의 순서번호에 해당하는 중복 ACK를 전송한다. 이 때, 보낼 세그먼트가 없더라도 ACK를 위해 헤더만 별도로 생성하여 송신측으로 전송한다. (ACK는 항상 세그먼트의 헤더에 포함되어 있음 - piggybacked ACK 방식)

 


- 위의 상황에서 발생한 갭(손실된 세그먼트)를 부분적으로 또는 모두 채워주는 세그먼트가 도착한 경우 => 부분적으로 도착하면 아직 받지 못한 세그먼트 중 가장 낮은(오래된) 순서번호의 ACK를 전송한다. 모두 도착했다면 위의 상황에서 높은 순서번호를 가진 세그먼트의 다음 세그먼트의 순서번호를 가진 ACK를 전송한다.

 

[ 왼쪽은 중복ACK, 오른쪽은 갭을 채우는 세그먼트가 모두 도착한 경우 ]

 

 

 

 

 

 

 

 

무명 클래스(Anonymous class)

 

- 말그대로 몸체는 있으나 이름만 없는 클래스를 의미하며, 하나의 객체만 사용할 경우에 이용한다. , 한번만 사용가능하다.


클래스명 변수명 = new 클래스명 { 클래스 몸체 };

 

- 무명 클래스의 선언은 하나의 실행문이므로 끝에 세미콜론(;)이 무조건 붙는다.

 

- 클래스명에 올 수 있는 것은 상속받고자 하는 부모 클래스의 이름이나 구현하고자 하는 인터페이스의 이름을 적어주면 된다.

 

- 무명클래스는 클래스를 정의하면서 동시에 객체를 생성하게 된다.

 

- 코드의 양을 줄일 수 있다는 장점이 있으나 코드가 난해해진다.

 

 

 

익명 구현 객체

 

- 무명클래스를 통해 인터페이스를 구현하고자 하는 일회성의 구현 객체를 말한다.

 

- 대부분 UI(user interface) 프로그래밍에서 이벤트를 처리하거나 임시 작업 스레드를 만들기 위해 익명 구현 객체를 많이 이용한다.

 

- 형식 


인터페이스타입 변수명 = new 인터페이스타입() {


//인터페이스에 선언된 추상메소드의 실체 메소드 선언


}; 



- 추가적으로 필드와 메소드도 선언이 가능하지만, 익명 객체 안에서만 사용할 수 있고, 해당 변수로는 접근할 수는 없다.





 

 

 

인터페이스(Interface)

 

- 추상 메소드들로만 이루어진 형태로, 객체의 사용 방법을 정의한 새로운 타입이다.

 

- 상수 외에 필드를 선언할 수 없다.

 

- 자바에서 인터페이스란 객체와 객체 사이의 상호 작용이 이루어지는 인터페이스이다.

 

- 추상 메소드의 성질을 이용하면, 인터페이스는 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라 실행 내용과 리턴값이 다를 수 있다.

 

- , 개발 코드를 수정하지 않고 사용하는 객체만 변경하여 메소드를 실행한다.

 

- 객체의 교환성을 높여주기 때문에 다형성을 구현하는 매우 중요한 역할을 한다.

 

상속은 같은 종류의 하위 클래스를 만드는 기술이고, 인터페이스는 사용 방법이 동일한 클래스를 만든다는 점에서 개념적인 차이가 있다. 그러나 둘 다 다형성을 구현하는 기술이다.


- 인터페이스를 구현하는 객체를 구현 객체라고 부르며, 구현 객체를 생성하는 클래스를 구현 클래스라고 부른다. 구현 클래스는 추상 메소드의 몸체를 반드시 구현하여야 한다.

 

- 인터페이스의 모든 메소드는 기본적으로 public 접근 제한자를 갖기 때문에 구현 클래스에서 작성할 때 public 보다 더 강한 접근 제한자(default, private )를 사용할 수 없다. , public을 생략해선 안된다.

 

- 상속과는 달리 구현 클래스는 다수의 인터페이스를 구현할 수 있다.

 

- 인터페이스끼리는 상속이 가능하다.

public interface 인터페이스1 extends 인터페이스2 { ... }

 

- 구현 클래스는 선언부에 implements 키워드를 추가하고 인터페이스 명을 명시해야 한다.

* implements 시행하다, 도구라는 뜻이다.

 

- 인터페이스 타입의 변수는 참조형 변수이기 때문에 구현 객체가 대입될 경우 구현 객체의 번지를 저장한다.


 


인터페이스의 구성 멤버

 

- 상수 필드 : 상수는 인터페이스에 고정된 값이므로 런타임 시에 데이터를 바꿀 수 없다. 상수를 선언할 때에는 반드시 초기값을 대입해야 한다.


public static final 자료형 변수명;


 

- 추상 메소드 : 객체가 사용할 메소드의 형태를 설명한 것으로, 어ᄄᅠᆫ 매개값이 필요하고 리턴 타입이 무엇인지만 알려준다. 실체 실행부는 해당 인터페이스를 구현하는 클래스에서 작성해야 한다.

 

- 디폴트 메소드 : 자바 8버전에서만 허용하는 멤버이며, 기존 인터페이스를 확장해서 사용하기 위함이다. 선언할 때 인터페이스를 구현한 실제 객체가 가지고 있는 메소드라고 생각하면 된다. 따라서 구현 객체에서는 인터페이스의 디폴트 메소드의 실체 메소드를 작성할 필요가 없다.

 

- 정적 메소드 : 자바 8버전에서만 허용하는 멤버이며, 디폴트 메소드와 달리 객체가 없어도 인터페이스만으로 호출이 가능하다. 쉽게 말해, 인터페이스를 선언하지 않고 "인터페이스이름.정적메소드명()"과 같이 바로 호출이 가능함.

 

 

 

인터페이스의 일반적인 형태

 

- 인터페이스의 모든 메소드는 추상 메소드로 간주되므로 abstract키워드는 사용하지 않는다.

 


public interface 인터페이스명 {

//상수

...

 

//추상 메소드

리턴타입 추상메소드1(...);

리턴타입 추상메소드2(...);

...


//디폴트 메소드 -> default를 붙여야한다. 안 붙이면 추상 메소드로 간주됨

default 리턴타입 메소드명(...) { ... }

...


//정적 메소드

static 리턴타입 메소드명(...) { ... }

}




public class 클래스명 implements 인터페이스명 {

 

//FIELDS

...

 

//CONSTRUCTOR

...

 

//METHODS

@Override

리턴타입 추상메소드1(...) {

    ...

}


@Override

리턴타입 추상메소드2(...) {

    ...

}

 

} 


- @Override 란 인터페이스의 추상 메소드에 대한 정확한 실체 메소드인지 컴파일러가 체크하도록 지시하는 어노테이션이다. 생략해도 상관없으나, 실체 메소드가 잘못되지 않도록 해주기 때문에 붙여 주는 것이 좋다.




▶ 인터페이스의 타입 변환


- 구현 객체가 인터페이스 타입으로 변환되는 것은 자동 타입 변환에 해당한다. 이렇게 자동 타입 변환된 구현 객체는 해당 클래스의 필드와 메소드를 사용할 수 없다. 즉, 인터페이스의 상수와 메소드만 사용가능하다.


- 반대로, 인터페이스 타입인 구현 객체를 강제 타입 변환하여 구현 클래스 타입으로 사용할 수 있다.


- 필드와 매개변수의 타입을 인터페이스로 선언하면 여러 구현 객체를 대입하여 다양한 실행 결과를 만들 수 있다.


+ Recent posts