앞에서 얘기했듯, TCP/IP 프로토콜 transport 계층에 몇 가지 프로토콜이 지정되었다
이 장에서는 TCP에 대해 설명하겠다
TCP는 광범위한 서비스를 제공하는 핵심이며, 복잡한 프로토콜이다
그림은 TCP와 TCP/IP의 다른 프로토콜에 대한 TCP의 관계를 보여준다
TCP는 애플리케이션 계층과 네트워크 계층 사이에 위치하며, 애플리케이션 프로그램과 네트워크 작업 사이의 중개자 역할을 한다
TCP
UDP는 connectionless에다 unreliable했다
TCP는 UDP보다 더욱 많은 기능을 제공한다
위의 기능들에 대해 알아보자
UDP와 마찬가지로 TCP는 포트 번호를 사용하여 프로세스 간 통신을 제공
UDP와 달리 TCP는 stream oriented 프로토콜이다
UDP
TCP
그림은 데이터의 한 방향으로 이동을 보여준다
sending buffer
송신버퍼에는 세 가지 유형의 칸이 있다
흰색 섹션
분홍색 영역
회색 영역
분홍색 영역의 바이트가 확인되면 영역은 재활용된다
receiving buffer
버퍼링은 두 프로세스 간의 속도 차이를 처리하지만, 데이터를 전송하려면 한 단계가 더 필요하다
IP 계층은 바이트 스트림이 아닌 패킷으로 데이터를 전송해야 한다
transport 계층에서 TCP는 여러 바이트를 세그먼트라고 불리는 패킷으로 그룹화한다
TCP는 각 세그먼트에 헤더를 추가하고(제어 목적으로) 해당 세그먼트를 IP 계층으로 전송한다
세그먼트들은 IP 데이터그램에 캡슐화되어 전송된다
그림은 버퍼의 바이트에서 세그먼트가 생성되는 것을 보여준다
세그먼트의 크기는 모두 동일할 필요는 없다
UDP와 달리 TCP는 연결 지향 프로토콜이다
A의 프로세스가 B의 다른 프로세스와 데이터를 주고받기를 원할 때, 다음과 같은 세 가지 단계가 발생한다
이 연결은 물리적 연결이 아닌 가상 연결이다
TCP 세그먼트는 IP 데이터그램에 캡슐화되어 있으며, 순서가 잘못되어 전송되거나 분실되거나 손상되어 재발송될 수 있다
각각은 목적지에 도달하기 위해 다른 경로를 통해 라우팅될 수 있다
TCP는 다른 프로세스로 바이트를 전달하는 스트림 oriented 환경을 만든다.
TCP의 여러 기능을 제공하기 위해 TCP에는 이 섹션에서 간략하게 요약하고 나중에 자세히 설명하는 몇 가지 기능이 있다
TCP는 전송 또는 수신되는 세그먼트를 추적하지만 세그먼트 헤더에는 세그먼트 번호 값에 대한 field가 없다
대신 sequence number와 acknowledgement number라는 두 개의 필드가 있다
이 두 개의 필드는 세그먼트 번호가 아닌 바이트 번호를 나타낸다
TCP는 전송되는 모든 데이터 바이트에 번호를 부여
각 연결에서 전송되는 데이터의 바이트는 TCP에 의해 넘버링
번호는 임의로 생성된 번호로 시작
세그먼트의 sequence number의 값은 해당 세그먼트에 포함된 첫 번째 데이터 바이트에 할당된 번호로 정의
TCP는 연결이 설정되면 양쪽 모두 동시에 데이터를 주고받을 수 있다
각 호스트?의 바이트 번호는 보통 다르다
각 방향의 시퀀스 번호는 전달되는 첫 번째 바이트 넘버이다
ack num
세그먼트에 있는 ack의 값은 당사자가 수신할 것으로 예상되는 다음 바이트의 수를 정의
ack 넘버는 누적된다
TCP에 대해 더 자세히 설명하기 전에 TCP 패킷 자체에 대해 알아보겠다
TCP에서 패킷을 세그먼트라고 한다
세그먼트는 20 ~ 60 바이트의 헤더와 애플리케이션 프로그램의 데이터로 구성된다
옵션이 없는 경우 헤더는 20바이트이고 옵션이 포함된 경우 최대 60바이트이다
TCP에서 체크섬은 의무적으로 사용한다
TCP는 연결 지향적이다
연결 지향 전송 프로토콜은 소스와 목적지 사이에 가상 경로를 설정한다
그러면 메시지에 속한 모든 세그먼트가 이 가상 경로를 통해 전송된다
전체 메시지에 대해 단일 가상 경로를 사용하면 확인 프로세스와 손상되거나 손실된 프레임의 재전송이 용이해집니다
요점은 TCP 연결이 물리적 연결이 아니라 가상이라는 것이다
TCP는 IP 서비스를 사용하여 개별 세그먼트를 수신자에게 전달하지만 연결 자체를 제어한다
세그먼트가 손실되거나 손상되면 다시 전송된다
TCP와 달리 IP는 이 재전송을 인식하지 못한다
세그먼트가 잘못된 순서로 도착하면 TCP는 누락된 세그먼트가 도착할 때까지 세그먼트를 유지한다
IP는 세그멘트의 순서를 알지 못한다
TCP에서 연결 지향 전송은 연결 설정, 데이터 전송, 연결 종료의 세 단계를 필요로 한다
TCP는 양방향으로 데이터를 전송한다
두 대의 컴퓨터에 있는 두 개의 TCP가 연결되면 서로 동시에 세그먼트를 전송할 수 있다
이는 데이터가 전송되기 전에 상대방으로부터 승인을 받아야 함을 의미한다
서버
클라이언트
클라이언트는 첫번째 세그멘트인 SYN(SYN 세그먼트)을 전송
SYN 세그먼트는 데이터를 전송할 수 없지만 하나의 시퀀스 넘버를 사용
서버는 두번째 세그멘트인 SYN + ACK 세그멘트를 전송
SYN + ACK 세그먼트는 데이터를 전송할 수 없지만 하나의 시퀀스 넘버를 사용
클라이언트가 세 번째 세그먼트인 ACK 세그먼트 보냄
ACK 세그먼트는 데이터가 없는 경우 시퀀스 번호를 사용하지 않는다
즉 동기화를 보내면 그에 맞는 응답(동기화 + 1) 값을 보내야하며 송수신버퍼 사이즈도 연결할때 보내야한다
연결이 설정된 후에는 양방향 데이터 전송이 이루어질 수 있다
클라이언트와 서버는 양방향으로 데이터와 확인 응답을 보낼 수 있다
시퀀스 및 ack 넘버의 값을 기록한다
클라이언트 서버 둘 다 연결을 닫을 수 있다
오늘날 대부분의 구현에서는 연결 종료를 위한 3 way 핸드셰이킹을 허용한다
FIN 세그먼트는 데이터를 전송하지 않는 경우 하나의 시퀀스 번호를 소비
서버 TCP는 FIN 세그먼트를 수신한 후 두 번째 세그먼트인 FIN+ACK 세그먼트를 전송
클라이언트 TCP는 마지막 세그먼트인 ACK 세그먼트를 전송하여 TCP 서버로부터 FIN 세그먼트의 수신을 확인
한 쪽은 연결 종료가 되었지만 다른 쪽은 계속 데이터를 받을 수 있다
서버 또는 클라이언트 중 하나가 하프 클로즈 요청을 실행할 수 있다
FIN + ACK 세그먼트는 데이터를 전송하지 않는 경우 하나의 시퀀스 번호를 소비
클라이언트에서 서버로 데이터 전송이 중지된다
클라이언트는 FIN 세그먼트를 전송하여 연결을 절반으로 닫는다
서버는 ACK 세그먼트를 전송하여 하프 클로즈를 수락한다
그러나 서버는 여전히 데이터를 전송할 수 있다
서버는 처리된 모든 데이터를 전송하면 클라이언트의 ACK에 의해 확인되는 FIN 세그먼트를 전송한다
Half close를 한 후 데이터는 서버에서 클라이언트로 전송되고 ack은 클라이언트에서 서버로 전송될 수 있다
클라이언트가 서버에 데이터를 더 이상 보낼 수 없다
두 번째 세그먼트(ACK)는 시퀀스 넘버를 사용하지 않는다
클라이언트가 시퀀스 넘버 y-1을 수신하고 y를 예상하지만 서버 시퀀스 넘버는 여전히 y -1이다
연결이 닫힐 때 마지막 ACK 세그먼트의 시퀀스 넘버는 여전히 x다
왜냐하면 해당 방향으로 데이터를 전송하는 동안 시퀀스 넘버가 소비되지 않기 때문이다
연결 설정, 연결 종료 및 데이터 전송 중에 발생하는 모든 다양한 이벤트를 추적하기 위해 TCP는 state 머신으로 나타내 진다
TCP state machine과 transition 다이어그램을 이해하기 위해 몇 가지 시나리오를 본다
클라이언트
클라이언트 프로세스는 TCP에 명령을 실행하여 특정 소켓 주소에 대한 연결을 요청
TCP는 SYN 세그먼트를 전송하고 SYN-SENT 상태로 이동
SYN+ACK 세그먼트를 수신한 후, TCP는 ACK 세그먼트를 전송하고 Established 상태로 이행
데이터는 양방향으로 전송되고 확인된다
클라이언트 프로세스에 보낼 데이터가 더 이상 없으면 active close라는 명령을 실행 클라이언트 TCP는 FIN 세그먼트를 전송하고 FIN-WAIT-1 상태로 이동
전송된 FIN에 대한 ACK를 수신하면 FIN-WAIT-2 상태가 되고 서버로부터 FIN 세그먼트를 수신할 때까지 유지
FIN 세그먼트가 수신되면 클라이언트는 ACK 세그먼트를 전송하고 TIME-WAIT 상태로 전환하고 최대 세그먼트 lifetime(MSL)의 2배의 시간 초과 값에 대한 타이머를 설정
time out이 되면 close
서버
첫 번째 FIN으로 시작하는 종료 단계를 4 way 핸드쉐이크라고 한다
위 transition 다이어그램을 timeline으로 구성한 그림
연결 설정 및 연결 종료 단계에서 3way 핸드쉐이크가 일반적이다
그림은 이 시나리오에서 클라이언트와 서버에 대한 transition 다이어그램이다
아래는 time line이다
연결종료 부분만 위의 timeline과 다르다
그림은 데이터 전송 단계 이후의 모습이다
동시에 열린 경우 두 응용 프로그램 모두 활성 상태로 열린다
이것은 클라이언트나 서버가 없는 드문 경우이다
이 경우는 TCP에 의해 허용되지만, 양쪽이 SYN 세그먼트를 서로 전송해야 하고 세그먼트가 동시에 전송되기 때문에 발생할 가능성은 낮다
그림은 이 시나리오에 대한 연결 설정 단계를 보여준다
두 TCP는 모두 Established 상태로 가기 전에 SYN-Sent 및 SYN-RCVD 상태를 거친다
자세히 보면 두 프로세스가 모두 클라이언트와 서버 역할을 한다는 것을 알 수 있다 두 개의 SYN+ACK 세그먼트가 SYN 세그먼트를 인식하고 연결을 연다
연결 설정에는 4way 핸드셰이크가 포함된다
이 경우 양쪽이 active close를 한다
두 TCP 모두 FIN-WAIT-1 상태로 전환되고 전송 중인 FIN 세그먼트를 동시에 전송한다
FIN 세그먼트를 수신한 후, 각 엔드는 CLOSING 상태가 되고 ACK 세그먼트를 보낸다
닫힘 상태는 공통 시나리오에서 FIN-WAIT-2 또는 CLOSE-WAIT를 대체한다
ACK 세그먼트를 수신한 후 각각 TIME-WAIT 상태로 이동한다
각 엔드가 손실될 수 있는 ACK를 전송했기 때문에 양 엔드에 이 기간이 필요하다
클라이언트 프로세스가 갑자기 끝냈을 때 상황이다
프로세스는 연결을 닫는 대신 연결을 중단할 수 있다
이러한 경우 모두 TCP는 RST 세그먼트를 전송하여 연결을 중단할 수 있다
TCP는 RST+ACK 세그먼트를 전송하고 대기열의 모든 데이터를 버린다
서버 TCP는 또한 대기 중인 모든 데이터를 삭제하고 오류 메시지를 통해 서버 프로세스에 알린다
두 TCP는 즉시 CLOSED 상태로 전환된다
RST 세그먼트에 응답하여 ACK 세그먼트가 생성되지 않는다
TCP에서의 데이터 전송과 flow, error 및 congestion 제어와 같은 문제에 대해 논의하기 전에 TCP에서 사용되는 window에 대해 설명한다
TCP는 데이터 전송의 각 방향에 대해 두 개의 윈도우(전송과 수신)을 사용하며, 이는 양방향 통신에 4개의 윈도우가 있다는 것을 의미한다
근데 여기선 쉽게 하기 위해 단일 통신으로 가정하겠당~
버퍼 얘기다 !!
그림은 송신 윈도우의 예다
송신 윈도우 크기가 flow control과 기본 네트워크의 혼잡(congestion control)에 의해 결정된다
flow control은 생산자가 데이터를 생성하는 속도와 소비자가 데이터를 사용할 수 있는 속도를 균형 있게 조정한다
TCP는 flow control과 error control를 분리한다
flow control을 설명하기 위해 일시적으로 송신 TCP와 수신 TCP 사이의 논리적 채널이 오류가 없다고 가정한다
그림은 송신자와 수신자 사이의 단방향 데이터 전송을 보여준다
상대방의 버퍼를 초과하지 않게 도와준다!
대부분의 TCP 구현체들은 수신 프로세스에서 수신 TCP로 flow control 피드백을 제공하지 않는다
전송 TCP에서 전송 프로세스(경로 5)로의 flow control 피드백은 창이 꽉 찼을 때 TCP를 전송함으로써 데이터의 간단한 거부를 통해 달성된다
수신 window
송신 window
그림은 연결 설정 단계에서 송수신 창이 어떻게 설정되는지, 그리고 데이터 전송 중에 해당 상황이 어떻게 변화하는지 보여준다
어떠한 세그먼트도 손상되거나, 분실되거나, 복제되거나, 고장 난 상태로 도착하지 않는다고 가정하여 error control을 무시한다
단방향 데이터 전송을 위한 창은 두 개뿐이다
오른쪽 벽을 왼쪽으로 이동하여 송신 윈도우를 축소하는 것은 매우 권장되지 않는다
그러나 한 가지 예외가 있다
receiver는 0의 rwnd를 전송하여 창을 일시적으로 종료할 수 있다
이 문제는 어떤 이유로든 수신자가 송신자로부터 데이터를 한동안 수신하지 않으려는 경우에 발생할 수 있다
이 경우 sender는 실제로 창 크기를 축소하지 않고 새 ad가 도착할 때까지 데이터 전송을 중지한다
TCP는 신뢰할 수 있는 전송 계층 프로토콜이다
즉, TCP에 데이터 스트림을 전달하는 응용 프로그램은 TCP에 의존하여 전체 스트림을 다른 쪽의 응용 프로그램에 데이터를 순서대로 오류 없이, 그리고 어떤 부분도 손실되거나 복제되지 않고 전달한다는 것을 의미한다
TCP는 error control을 사용하여 신뢰성을 제공한다
오류 제어에는 손상된 세그먼트를 감지 및 다시 보내기, 손실된 세그먼트를 다시 보내기, 누락된 세그먼트가 도착할 때까지 잘못된 세그먼트를 저장하기, 중복된 세그먼트를 감지 및 폐기하기 위한 메커니즘이 포함된다
TCP의 오류 제어는 체크섬, ack, time out이라는 세 가지 간단한 도구를 사용하여 이루어진다
TCP는 ack를 사용해 데이터 세그먼트의 수신을 확인한다
데이터가 전송되지 않지만 시퀀스 번호를 소비하는 제어 세그먼트도 ack이다
ACK 세그먼트는 ack되지 않는다
ACK 세그먼트는 시퀀스 번호를 소비하지 않으며 ack되지 않는다
TCP는 순서가 뒤바뀐 세그먼트를 폐기하지 않는다
이러한 세그먼트는 해당 세그먼트를 임시로 저장하고 누락된 세그먼트가 도착할 때까지 out of order 세그먼트로 태그된다
그러나 순서가 잘못된 세그먼트는 프로세스에 전달되지 않는다
TCP는 데이터가 순서대로 프로세스에 전달되도록 보장한다
데이터는 수신 TCP에 의해 일시적으로 저장될 수 있지만, TCP는 프로세스에 잘못된 데이터가 전달되지 않도록 보장한다
두 시스템 간의 양방향 데이터 전송을 보여준다
클라이언트 TCP는 하나의 세그먼트를 보내고 서버 TCP는 세 개의 세그먼트를 보낸다
그림은 각 ack에 적용되는 규칙을 보여준다
클라이언트의 첫 번째 세그먼트와 세 개의 서버 세그먼트 모두에 규칙 1이 적용된다
전송해야 할 데이터가 있으므로 세그먼트에 예상되는 다음 바이트가 표시된다
클라이언트는 서버로부터 첫 번째 세그먼트를 수신하면 더 이상 전송할 데이터가 없으며 ACK 세그먼트만 전송하면 된다
그러나 규칙 2에 따르면, 더 많은 세그먼트가 도착하는지 확인하기 위해 500ms 동안 ack를 지연해야 한다
ACK 지연 타이머가 만료되면 ack를 보낸다
이는 클라이언트가 자신에게 다른 세그먼트가 올지 말지 모르기 때문이다
다음 세그먼트가 도착하면 다른 ACK 지연 타이머가 설정된다
그러나 타이머가 다 되기 전에 세 번째 세그먼트가 도착한다
세 번째 세그먼트의 도착은 규칙 3에 기초한 다른 ack를 작동시킨다
세그먼트가 손실되거나 지연되지 않기 때문에 RTO 타이머를 표시하지 않았다
세그먼트가 손실되거나 손상되었을 때 어떤 일이 일어나는지 보여준다
손실된 세그먼트는 네트워크 어딘가에서 폐기된다
손상된 세그먼트는 receiver 자체에 의해 폐기된다
둘 다 분실된 것으로 간주된다
그림은 세그먼트가 손실되는 상황을 보여준다
sender는 세그먼트 1과 2를 보내며, 이는 ACK에 의해 즉시 인식된다(규칙 3)
그러나 세그먼트 3은 손실된다
receiver는 순서가 잘못된 세그먼트 4를 수신한다
receiver는 세그먼트의 데이터를 버퍼에 저장하지만 데이터에 연속성이 없음을 나타내기 위해 간격을 둔다
receiver는 기대하는 다음 바이트(규칙 4)를 표시하는 ack를 sender에게 즉시 보낸다
receiver는 바이트 801에서 900을 저장하지만 간격이 좁혀질 때까지 이 바이트를 애플리케이션에 전달하지 않는다
수신기 TCP는 순서가 지정된 데이터만 프로세스에 전달합니다.
빠른 재전송을 보여준다
receiver는 네 번째, 다섯 번째, 여섯 번째 세그먼트를 수신할 때마다 ack를 트리거한다(규칙 4)
sender는 동일한 값(3개의 중복)을 가진 4개의 ack를 수신한다
타이머가 끝나지 않았음에도 불구하고, 빠른 전송을 위한 규칙은 이러한 모든 중복 ack에 의해 예상되는 세그먼트 3을 즉시 재발송해야 한다
이 세그먼트를 다시 보낸 후 타이머가 다시 시작된다
손실된 ack가 다음 ack에 포함되는 상황을 보여준다
ack는 누적될 수 있다
그림은 데이터 수신기가 보낸 손실된 ack를 보여준다
다음 ack는 자동으로 ack의 손실을 수정한다
그림은 ack가 손실되는 시나리오를 보여준다
다음 ack가 오랫동안 지연되거나 응답이 없는 경우 RTO 타이머에 의해 다시 응답없는 세그멘트를 전송한다
중복 세그먼트가 결과이다
receiver는 중복 세그먼트를 수신하면 해당 세그먼트를 폐기하고 마지막 ACK를 즉시 재전송하여 송신자에게 세그먼트가 수신되었음을 알린다
두 개의 세그먼트가 승인되지 않지만 한 개의 세그먼트만 재전송된다
송신자가 재전송된 ACK를 수신하면, ack가 누적되기 때문에 두 세그먼트가 모두 안전하고 정상임을 알 수 있다
확인이 손실되면 제대로 처리되지 않으면 교착 상태가 발생할 수 있다
TCP의 혼잡 제어는 open loop와 closed loop 메커니즘을 기반으로 한다
TCP는 정체를 피하고 정체가 발생하면 이를 감지하고 완화한다
cwnd가 2의 지수적으로 증가한다
sender는 cwnd = 1 으로 시작한다
즉, 보낸 사람이 세그먼트를 하나만 보낼 수 있다
첫 번째 ACK가 도착한 후 정체 윈도우의 크기는 1만큼 증가하며, 이는 cwnd가 현재 2라는 것을 의미한다
이제 두 개의 세그먼트를 보낼 수 있다
두 개의 ACK가 도착하면 cwnd가 이제 4가 된다
이제 4개의 세그먼트를 더 보낼 수 있다
4개의 ACK가 도착하면 창의 크기가 4만큼 증가하는데, 이는 cwnd가 현재 8이라는 것을 의미한다
이 지수적 증가는 무한정 계속할 수 없다
이 단계를 중지하려면 임계값이 있어야 한다
sender는 sstresh(느린 시작 임계값)라는 변수를 보면서 창 크기가 이 값에 도달하면 지수적 증가가 중지되고 다음 단계가 시작된다
느린 시작 알고리즘에서 정체 창의 크기는 임계값에 도달할 때까지 기하급수적으로 증가합니다.
느린 시작 알고리즘으로 시작하면 정체 윈도우의 크기가 기하급수적으로 증가한다
혼잡이 발생하기 전에 혼잡을 피하려면, 이 지수 성장을 늦춰야 한다
TCP는 congestion 회피라고 불리는 또 다른 알고리즘을 정의한다
cwnd = i인 경우 정체 창의 크기가 느린 시작 임계값에 도달하면 느린 시작 단계가 중지되고 추가 단계가 시작된다
이 알고리즘에서 세그먼트의 전체 "윈도우"가 승인될 때마다 정체 윈도우의 크기가 1씩 증가한다
윈도우크기는 전송된 세그먼트 수이다
cwnd가 더하기로 증가한다
혼잡 회피 알고리즘에서 혼잡 창의 크기는 혼잡이 감지될 때까지 부가적으로 증가한다.
정체가 발생하면 정체 창 크기를 줄여야 한다
receiver가 혼잡이 발생했다고 추측할 수 있는 유일한 방법은 세그먼트를 재전송해야 하는 것이다
재전송은 RTO 타이머가 시간 초과되거나 세 개의 중복 ACK가 수신되는 두 가지 경우 중 하나에서 발생할 수 있다
두 경우 모두 임계값이 절반으로 떨어진다
임계값은 처음에는 16개 세그먼트(최대 창 크기의 절반)로 설정된다
느린 시작 단계에서 창 크기는 1부터 시작하여 임계값에 도달할 때까지 기하급수적으로 증가한다
임계값에 도달한 후 "더하기 증가" 절차를 사용하면 시간 초과가 발생하거나 최대 창 크기에 도달할 때까지 창 크기가 선형적으로 증가할 수 있다
창 크기가 20일 때 시간 초과가 발생한다
이 때 곱셈 감소 절차가 처리를 이어받아 임계값을 창 크기의 절반으로 줄인다
타임아웃이 발생했을 때 창 크기가 20이었으므로 현재 새 임계값은 10이다
TCP는 느린 시작으로 다시 이동하고 창 크기가 1로 시작하며 새 임계값에 도달하면 추가 증가로 이동한다
창 크기가 12이면 3ACK 이벤트가 발생한다
곱셈 감소 절차가 다시 이어진다
임계값과 창 크기가 6으로 설정되고 TCP가 이번에는 추가 증가 단계로 들어간다
TCP는 다른 시간 초과 또는 다른 3-ACK 이벤트가 발생할 때까지 이 단계를 유지한다
원활한 작동을 위해 대부분의 TCP 구현은 최소 4개의 타이머를 사용한다
TCP 헤더에는 최대 40바이트의 옵션이 포함될 수 있다
옵션은 추가 정보를 대상에 전달하거나 다른 옵션을 정렬한다
1바이트 옵션과 다중바이트 옵션이라는 두 가지 옵션이 있다
1바이트 옵션에는 옵션 목록 종료와 작업 없음이라는 두 가지 유형의 옵션이 있다
다중 바이트에는 최대 세그먼트 크기, 창 스케일 팩터, 타임스탬프, SACK 허용 및 SACK의 다섯 가지 유형의 옵션이 있다