- 재전송 타이머 값이 종종 상대적으로 길어지므로, 손실된 패킷의 재전송 전에 지연시간이 커진다.
- 위의 상항을 해결하고자 중복 ACKs를 통해 손실된 세그먼트를 검출한다.
- 송신측에서 바로바로 여러 개의 세그먼트를 전송할 경우, 세그먼트가 손실되면 수신측에서는 중복 ACK를 보내게 되는데, 타임아웃 전에 송신측에서 중복 ACK를 3번받게 되면 세그먼트를 즉시 전송한다.즉, 수신측이 기다리는 순서번호의 세그먼트보다 큰 순서번호의 세그먼트가 3개 도착할 경우를 의미한다.
- 점대점(Point-to-Point) : 단일 송/수신자간의 통신 ex) 일대일 통신, Unicast 전송
Unicast : 고유 주소로 식별된 하나의 네트워크 목적지에 메시지를 전송하는 방식
Broadcast : 송신 가능한 모든 목적지에 동일한 데이터를 전송
Multicast : 특별한 주소 지정 방식을 통해 정해진 여러 목적지로 데이터를 전송
호스트가 무수히 많은 경우, Unicast로 데이터를 전송하면, 각각의 네트워크 연결마다 호스트의 컴퓨팅 리소스(자원)을 소비할 뿐 아니라 각각 다른 네트워크 대역폭을 필요로 하기 때문에 전송 비용이 많이 든다는 단점이 있다.
- 파이프라인(Pipeline) : TCP의 혼잡 제어 및 흐름 제어가 윈도우 크기(Window size)를 결정한다.
Window size : ACK받지 않은 데이터 중 최대 송신가능한 바이트 수, 수신자가 한 번에 버퍼링할 수 있는 최대 데이터 크기
Sliding Window: 두 개의 네트워크 호스트 간의 패킷의 흐름을 제어하기 위한 방법으로, TCP 프로토콜은 데이터의 전달을 보증해야 하므로 패킷 하나 하나가 정상적으로 전달되었음을 알리는 확인 신호(Acknowledgement, ACK)를 수신자가 송신자에게 보내야 한다.
패킷에 오류가 생겼을 경우, 송신측에서 해당 패킷을 재전송해야 하는데 이 때 Sliding Window가 Window 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계층 기준 IPv4는 MSS 크기에서 40byte(IP헤더+TCP헤더)를 추가한 576Byte이고, IPv6는 1280Byte이다.
실제로는 최대 65,646바이트 범위까지 생성가능하다.
- MTU가 IP 기반의 정보인 반면, MSS는 TCP 기반의 정보이다.
- TCP는 연결지향형으로 제어 메시지들의 교환(Handshaking)이 이루어진다. 핸드쉐이킹을 통해 데이터 교환 전에 송신자 및 수신자의 상태를 초기화한다.
- 흐름 제어(Flow Control) : 수신자의 속도에 맞춰서 송신자가 데이터를 보낸다.
- 기다리는 것보다 높은 순서번호를 가진 세그먼트가 도착. 즉, 송신측에서 여러 개의 세그먼트를 전송한 후 중간 세그먼트가 손실된 경우 => 즉시 기다리는 바이트의 순서번호에 해당하는 중복 ACK를 전송한다. 이 때, 보낼 세그먼트가 없더라도 ACK를 위해 헤더만 별도로 생성하여 송신측으로 전송한다. (ACK는 항상 세그먼트의 헤더에 포함되어 있음 - piggybacked ACK 방식)
- 위의 상황에서 발생한 갭(손실된 세그먼트)를 부분적으로 또는 모두 채워주는 세그먼트가 도착한 경우 => 부분적으로 도착하면 아직 받지 못한 세그먼트 중 가장 낮은(오래된) 순서번호의 ACK를 전송한다. 모두 도착했다면 위의 상황에서 높은 순서번호를 가진 세그먼트의 다음 세그먼트의 순서번호를 가진 ACK를 전송한다.
- 추상 메소드의 성질을 이용하면, 인터페이스는 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라 실행 내용과 리턴값이 다를 수 있다.
- 즉, 개발 코드를 수정하지 않고 사용하는 객체만 변경하여 메소드를 실행한다.
- 객체의 교환성을 높여주기 때문에 다형성을 구현하는 매우 중요한 역할을 한다.
- 상속은 같은 종류의 하위 클래스를 만드는 기술이고, 인터페이스는 사용 방법이 동일한 클래스를 만든다는 점에서 개념적인 차이가 있다. 그러나 둘 다 다형성을 구현하는 기술이다.
- 인터페이스를 구현하는 객체를 “구현 객체”라고 부르며, 구현 객체를 생성하는 클래스를 “구현 클래스”라고 부른다. 구현 클래스는 추상 메소드의 몸체를 반드시 구현하여야 한다.
- 인터페이스의 모든 메소드는 기본적으로 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란 인터페이스의 추상 메소드에 대한 정확한 실체 메소드인지 컴파일러가 체크하도록 지시하는 어노테이션이다. 생략해도 상관없으나, 실체 메소드가 잘못되지 않도록 해주기 때문에 붙여 주는 것이 좋다.
▶ 인터페이스의 타입 변환
- 구현 객체가 인터페이스 타입으로 변환되는 것은 자동 타입 변환에 해당한다. 이렇게 자동 타입 변환된 구현 객체는 해당 클래스의 필드와 메소드를 사용할 수 없다. 즉, 인터페이스의 상수와 메소드만 사용가능하다.
- 반대로, 인터페이스 타입인 구현 객체를 강제 타입 변환하여 구현 클래스 타입으로 사용할 수 있다.
- 필드와 매개변수의 타입을 인터페이스로 선언하면 여러 구현 객체를 대입하여 다양한 실행 결과를 만들 수 있다.