연결 지향형
흐름제어
혼잡제어
reliablity
전이중 서비스
점대점 연결
cumulative ACKs
파이프라이닝
TCP는 큰 파일을 전송할 때 일반적으로 MSS(maximum segment size)크기로 파일을 분절한다.
그 세그먼트의 구조는 아래와 같다.

다른 구조들과 유사하게 헤어필드와 데이터 필드로 나뉜다.
출발지와 목적지 포트번호를 포함하고
32비트의 순서 번호 필드와 ACK필드가 사용된다.
16비트의 수신 윈도우 필드는 흐름제어에 사용된다.
헤더길이 필드는 TCP헤더의 길이를 나타내는데 옵션필드 때문에 가변적인 기링가 될 수 있다.
플래그 필드에는 여러가지가 포함된다.
ACK - ACK필드의 값이 유용함을 나타냄
RST(reset), SYN(sync), FIN(finish) - 연결 설정과 해제에 사용
PSH - 데이터를 상위계층에 즉시 전달해야함
URG - 긴급으로 표시, 긴급 데이터 포인터 필드가 가리킴
순서 번호와 확인응답 번호가 가장 중요하다.
TCP는 데이터를 정렬되어 있는 바이트 스트림으로 본다.

따라서 세그먼트에 대한 순서번호는 세그먼트에 있는 첫 바이트의 바이트 스트림 번호이고
확인응답 번호는 송신측의 호스트가 수신측의 호스트로부터 기대하는 다음 바이트의 순서번호다.
또한 TCP는 cumulative ACK 누적 확인응답을 제공하는데
스트림에서 첫번 째 잃어버린 바이트까지의 바이트들까지만 ACK를 보내는 것에서 확인할 수 있다.
한 ACK를 받으면 그 이전의 세그먼트들에 대해서 모두 제대로 수신했다고 판단하는 것이다.
신뢰적 전송을 위해 타이머를 설정한다.
그럼 타임아웃 주기를 정해야 하는데 그 주기는 RTT보다 조금 커야한다.
그럼 RTT는 어떻게 측정할까?
먼저 SampleRTT라는 샘플RTT를 구한다.
이 값은 세그먼트가 송신된 시간으로부터 그 세그먼트에 대한 ACK가 도착한 시간까지의 시간이다.
모든 세그먼트에 대해 이 값을 측정하지는 않고 한 번에 하나의 측정만을 한다.
재전송한 세그먼트에 대해서는 계산하지 않는다.
이 값은 세그먼트마다 다르고 불규칙적인데 그래서 SampleRTT값의 평균값EstimatedRTT)을 구한다.
ACK를 수신하고 새 SampleRTT를 획득할 때마다

이 공식에 따라 갱신한다.
알파는 0.125로 권장한다.
이 값은 가중평균으로 예전 샘플보다 최근 샘플에 높은 가중치를 준다.
RTT의 변화율도 유용하게 사용된다.
RTT변화율을 의미하는 DevRTT를 SampleRTT가 EstimatedRTT로부터 얼마다 많이 떨어지는지에 대한 값으로 정의한다.

타임아웃 주기는 EstimatedRTT를 기반으로 구하게된다.
하지만 이 값보다 너무 커도 작아도 안된다.
약간의 여윳값을 더한 값으로 설정하는데 SampleRTT값에 많은 변동이 있으면 여윳값이 커야하고 변동이 작을 때는 작아야한다. 따라서 이 때 DevRTT가 사용된다.

자신의 수신 버퍼로부터 읽은 데이터 스트림이 손상되지 않았으며 손실이나 중복이 없다는 것과 순서가 유지된다는 것을 보장

그림에서 송신자는 순서번호 92와 8바이트 데이터를 전송한다.
이에 따라 수신자는 ACK번호 100을 보낼 것이고 송신자는 이를 기다릴 것이다.
그런데 이 세그먼트가 손실된다면 타임아웃이 일어나고 같은 세그먼트를 재전송할 것이다.
송신자가 연속해서 두 세그먼트를 전송한다.
두 세그먼트가 모두 수신자에게 잘 도착한다면 ACK가 올것을 기다린다.
하지만 타임아웃 전에 어떤 ACK도 수신하지 못한다.
그럼 송신자는 다시 첫 세그먼트를 재전송하고 타이머를 다시 시작한다.
그럼 수신자는 cumulative ACK를 보낼 것이고 타임아웃 이전에 두번째 세그먼트에 대한 ACK가 도착한다면 송신자는 두번째 세그먼트를 재전송하지 않을 것이다.

첫 세그먼트의 ACK가 손실되었지만 타임아웃 전에 두번째 세그먼트에 대해 ACK를 받는다면 수신자가 모든 데이터를 수신했음을 안다.

송신자는 중복ACK에 의한 타임아웃이 일어나기 전에 패킷 손실을 발견한다.
중복ACK는 수신자가 기다리던 것 보다 더 큰 순서번호의 세그먼트를 받았을 때 가 장 최근에 보낸 ACK를 보내는 것으로 수신자는 데이터 스트림에서 간격(손실 세그먼트)을 찾을 수 있다.
송신자가 같은 데이터에 대해 3개의 중복확인 응답을 수신한다면 ACK된 세그먼트의 다음 3개의 세그먼트가 분실되었음을 알고 타임아웃 전에 손실 세그먼트를 재전송하는 빠른 재전송을 한다.
TCP연결의 종단에서 호스트들은 연결에 대한 개별 수신버퍼를 설정한다.
애플리케이션이 데이터를 읽는 속도가 느리다면 송신자가 더 많은 데이터를 빠르게 전송함으로 수신버퍼에 오버플로를 발생시킨다.
이렇게 버퍼를 오버플로시키는 것을 방지하기 위해 TCP는 흐름제어 서비스를 제공한다.
수신하는 애플리케이션이 읽는 속도와 송신자가 전송하는 속도를 같게한다.
송신자는 수신윈도(rwnd)라는 변수를 유지해 흐름제어를 제공한다.
수신 윈도는 수신 측에서 가용한 버퍼 공간이 얼마나 되는지 송신자에게 알려주는데 사용된다.
수신 버퍼의 크기 - RcvBuffer
애플리케이션에 의해 읽힌 데이터 스트림의 마지막 바이트 번호 - LastByteRead
수신 버퍼에 저장된 데이터 스트림의 마지막 바이트 번호 - LastByteRcvd
LastByteRcvd - LastByteRead <= RcvBuffer
rwnd = RcvBuffer - [LastByteRcvd - LastByteRead]
rwnd는 버퍼의 여유공간으로 설정된다.
rwnd를 통해 버퍼에 얼마만큼의 여유공간이 있는지 알린다.

#### TCP연결 해제
1. 클라이언트는 종료 명령을 내리고 이는 클라이언트 TCP가 서버에 1로 설정된 FIN비트를 포함한 세그먼트를 보낸다.
2. 서버가 이 세그먼트를 수신하면 서버는 ACK세그먼트를 보낸다.
3. 그 다음 FIN비트가 1로 설정된 자신의 종료 세그먼트를 송신한다.
4. 마지막으로 클라이언트는 서버의 종료 세그먼트에 ACK를 보낸다. 이 때 모든 자원 할당이 해제되고 연결이 끊긴다.