연결을 할 때는 3 way-handshake를 사용(연결을 끊을 때는 4 way-handshake)
데이터의 순차 전송을 보장(sequence number)
송수신자간의 데이터 처리 속도를 해결(흐름 제어)
네트워크 혼잡을 제어(혼잡 제어)
오류 감지(checksum)
데이터를 일정 크기만큼 잘라서 전송(세그먼트화)
3-way handshake
client가 syn 비트가 1인 패킷을 server로 송신(syn_sent)
server는 패킷을 받았다는 의미로 ack 비트를 1로 설정
이때, TCP는 양방향 통신이기 때문에 server에서도 client에 연결을 위한 syn 비트도 1로 설정해서 전송(syn_rcvd)
client는 server 보낸 syn/ack 패킷에서 연결 요청인 syn을 확인하고 server로 ack 비트가 1인 패킷을 전송(established)
이렇게 연결을 마치고 데이터를 송수신 하게 됨
syn 패킷을 보내고 ack 패킷을 받는 시간을 round trip time(rtt)라 함
이 과정에서 혼잡 제어 정책과 MSS(Maximum Segment Size) 정보를 교환
4-way handshake
데이터 전송을 끝마친 client가 server로 fin 비트가 1인 패킷을 전송
server는 이에 대한 ack 패킷을 전송
server도 데이터 전송을 끝마치기 위해 남은 패킷을 모두 전송하고 fin 패킷을 전송
client도 fin 패킷을 받게 되면 ack 패킷을 전송하고 연결을 마치게 됨
신뢰성
client가 데이터를 전송
server는 이에 대한 ack를 전송
하지만 server가 데이터를 받지 못해 ack를 전송하지 못한다면, client는 잠시 기다렸다가 데이터를 재전송하게 됨
이를 통해 신뢰성을 보장받을 수 있음
Nagle Algorithm : 작은 크기의 데이터를 보낼 때 헤더의 크기가 더 큰 경우 이는 비효율적인 전송 -> 이를 해결하기 위해 등장, window size와 보낼 데이터가 MSS보다 큰 경우 바로 전송 -> 이후의 데이터를 ack를 받을 때까지 버퍼에 저장 -> ack가 도착하면 버퍼에 있는 내용을 전송해 패킷의 수(pps)를 줄이는 방식
순차 전송
client가 데이터를 보낼때 랜덤한 sequence number와 함께 전송
server는 받은 데이터에서 sequence number + 1을 한 ack를 전송
이를 통해 순차 전송을 보장
흐름 제어(Flow Control)
수신측은 받은 데이터를 저장하는 일종의 Buffer가 존재
송신자로부터 데이터를 받으면서 Buffer안에 남은 크기(window size)를 ack 비트를 보낼 때 함께 보냄
이를 받은 수신자는 다음에 보낼 데이터의 크기가 Buffer안에 남은 크기보다 큰 지 비교하고 그렇다면, 전송하지 않음(wait 상태)
wait 상태는 프로세스가 소켓에 있는 데이터를 읽는 속도에 따라 달라짐
읽는 속도가 데이터를 받는 속도보다 빠르다면, TCP Buffer의 크기는 채워지지 않기 때문에 wait 상태에 걸리지 않음
만약 느리다면, TCP Buffer에 있는 데이터를 프로세스가 읽어서 비워질 때까지 wait
Stop and Wait : 데이터를 보내고 ack를 수신해야 다음 데이터 전송
Sliding Window : 송신측에서 보낼 데이터를 윈도우 크기만큼 설정하고 보낼때마다 옆으로 이동
혼잡 제어(Congestion Control)
TCP 연결이 처음 이루어질때 전송 속도를 천천히 증가 -> 송신 측이 ACK 패킷을 수신할 때마다 전송하는 데이터 양을 증가시킴
그러다 전송 속도가 혼잡을 일으킬 정도가 되고 데이터가 손실나면, window size를 줄여 전송 속도를 조절
AIMD : window size를 1씩 증가, 처음에 너무 느리다는 단점
Slow Start : window size를 2배씩 증가, 혼잡이 발생하면 window size를 1로 하고 혼잡이 발생한 window size 크기의 반만큼은 다시 2배씩 증가하다가 이후로는 1씩 증가
Fast Retransmit : 송신자가 ack를 수신받지 못하면 데이터가 손실되었다고 생각하고 데이터를 재전송