1. fast retransmit
TCP는 timeout 값을 결정하는 것이 중요합니다.
TCP는 RTT 값을 측정해서 timeout의 기준점을 삼습니다.
문제는 RTT는 변동성이 심하다는 것입니다. 이 변동성을 잡아주기 위해서 moving average를 활용했습니다. 과거까지 moving average를 한 것과 현재 측정한 RTT를 가중치 평균을 해서 계속 업데이트 해 나갑니다.
여기에 또 safety margin을 붙입니다. 이는 편차에 대한 moving average 값입니다.
TCP에서 ack을 piggybacked 해서 날아갑니다. ack만 날아가는 패킷을 최대한 줄여보기 위해 생겼죠.
ack을 지연시키는 delayed ack이라는 기법을 사용해서 데이터에 같이 ack 실어서 보냅니다.
1-1. 타임아웃 터지기 전에 재전송을 보낼 순 없을가?
TCP는 타임아웃이 터져야 패킷을 재전송 할 수 있습니다. (like 고백엔) 하지만 떄때로 타임아웃 값을 기다리는게 시간이 너무 오래걸린다고 생각할 수 있습니다. 타임아웃이 터지기 전에 재전송을 보낼 수 있는 방법을 없을까 생각하게 됩니다. 타임아웃이 터지기 전에 패킷 로스를 감지를 해야할 텐데요.
ack은 항상 앞에 패킷에 대한 ack이 날라옵니다. sender는 중복된 ack이 계속온다는 말로 이 다음 패킷이 로스가 될 확률이 높다는 것을 알 수 있습니다.
이런 원리에서 fast retransmit 방식이 나왔습니다.
중복된(duplicate) ack을 연속해서 받으면 타임아웃되기 전에 재전송을 하자!
약 3개의 중복 ack을 받으면 재전송합니다. (3 duplicate ack)
3 duplicate ack이 있다면 ack을 안받은 것 중 가장 작은 시퀀스 넘버 패킷을 재전송합니다. 하나씩 하나씩 재전송해요~! 뒤에꺼는 중간에 로스가 나도 뒤에건 제대로 갔을 수 있기 때문입니다.(뒤에건 버퍼링 한다는 말)
1-2. TCP=GO-BACK-N+SR
TCP는 GO-BACK-N과 SR 방식이 적절히 섞여진 형태입니다.
TCP는 GO-BACK-N처럼 cummulative ack 방식으로 진행합니다. 가장 작은 시퀀스 넘버랑 액을 안받은거 중에서 가장 작은 시퀀스넘버, 윈도우 내에서 다음에 보낼 수 있는 시퀀스 넘버를 관리합니다.
TCP는 SR처럼 out of order 세그먼트를 저장합니다. 재전송할 때 1개의 패킷만 재전송합니다.
2. flow control
flow control이나 congestion control은 윈도우 사이즈를 결정하기 위한 기능입니다.
윈도우 상황이 너무 좋으면 윈도우 사이즈를 최대한 키우는 것이 좋습니다. 그 반대면 줄여야겠죠.
하지만 윈도우 사이즈 키우는 것도 수신단이 읽어들이는 속도보다 네트워크를 통해서 밀려들어오는 데이터가 많다면 안되겠죠. 메모리 사이즈는 무제한이 아니기 때문에 로스가 일어날 수 있습니다.
즉 윈도우 사이즈를 결정할 때 네트워크 상황도 고려해야하고, 수신단이 얼만큼의 속도로 데이터를 받을 준비가 되어있는지 고려해야합니다. (수신단의 버퍼 상태)
TCP헤더에는 receive window라는 필드가 있는데, 이 필드에 수신자가 ack을 보낼 때 이 필드를 채워서 알려주게 되는겁니다.
이 안에 정보로는 "수신자의 남은 버퍼 사이즈(오버플로우 방지)"를 알려줍니다. 이게 flow control 알고리즘입니다.
free buffer space를 TCP 헤더 receive window라는 필드에 적어줘서 피드백을 줍니다. 5년전 삼성만해도 리시브 버퍼를 2메가 썼고, 현재는 더 커졌을 거 같네요 (명시된 4000바이트는 아니란 소리)
또한 리시브 버퍼가 오버플로우되는 것을 막기 위해서 rwnd 기준으로 limit을 겁니다.
congestion window를 cwnd라고 합니다. 뒤에서 배울 예정입니다. 네트워크 상황에 맞게 윈도우 조정을 해요.
이 값은 rwnd 값을 넘으면 안되는 것이죠.
그렇기에 최종 윈도우 사이즈는 min(cwnd, rwnd)라고 표현할 수 있는 것입니다. 네트워크 상황이 너무 좋으면 cwnd로 결정이되는 것이고, 단말이 못따라줄 경우 rwnd로 보통 결정이 됩니다.
3. connection management
커넥션을 맺으면 커넥션 상태를 관리합니다. 커넥션이 유지할 동안은 헤더에 적힌 내용들을 관리하게 됩니다.
UDP 보다는 프로세스 관점에서 부하가 당연히 있을 수 밖에 없어요 UDP는 상태 관리 안하거든요.
TCP는 연결을 요청할 때 이니셜 시퀀스 넘버를 하나 고릅니다. (랜덤으로) 32bit에서 랜덤하게 골라요.
그럼 거기서 부터 시퀀스 번호가 시작이 됩니다(항상 0번부터 시작되는 것은 아닙니다.)
SYNbit의 의미는 "나는 연결을 맺고 싶어"라는 의미입니다. TCP헤더에 S필드는 처음 연결 맺을 때 1로 세팅됩니다. 1이라는 말은 연결을 맺기 위해 사용하는 TCP패킷을 나타냅니다. 동시에 시퀀스번호가 들어가 이 시퀀스 번호부터 사용할 것을 암시해줍니다.
서버에서도 SYNbit에 대한 ack을 보내줍니다. ACKbit을 1로 보내면서, 클라이언트가 보낸 SYNbit에 대한 bit임을 암시합니다. TCP헤더의 A필드는 1이 되는 것이죠.
또 본인이 사용할 시퀀스 번호를 셋팅 후 ack을 보내는 겁니다.
시퀀스넘버 x가 왔으니 acknum은 +1을 해주고 보냅니다. SYNbit이 1이왔기 때문이죠.
여기까지 수행되면 server는 리슨상태에서 SYNSENT상태로 변화되며, client는 SYN RCVD상태로 변화됩니다.
클라이언트가 ACKbit을 잘받았다는 것은 나랑 소통할 서버가 살아있다는 것을 알게되는 것 입니다. 대화가 가능한 상태를 알게되는 것입니다. 그리고 최종 ack을 보내는데요. Y+1로 보내게 됩니다.
서버도 위의 액을 받고 클라이언트도 내가 보낸 ack을 제대로 받았고 나랑 소통할 준비가 되어있다는 것을 알게되는 것이죠.
그 다음부턴 데이터를 주고 받을 수 가 있는 것입니다. 3번째 액을 보낼 때 데이터를 piggybacked해서 보낼 수 있는 것이죠. 따로 데이터를 보내도 되고요.
위 처럼 3번 왔다갔다 3 hand-shake를 실행한 끝에 메세지를 주고 받을 수 있는 겁니다.
그렇다면 왜 3 way hand-shake를 실행할까요?
클라이언트가 서버가 살아있는지 모르기 때문에 죽어있다가 데이터가 낭비될 수 있다.
연결되어 있는 지 확실치 않은 상태에선 로스가 발생될 수 있다.
2way로 하면 어떤 문제가 있을까요?
클라이언트가 연결 시도 했으니 아는 것 아닌가? 생각할 수도 있습니다.
연결을 시도했는데 클라이언트가 연결을 끊어버리면, 서버가 낭비가 될 수 있다
(답)
UDP인 경우 커넥션을 맺는 절차가 없습니다. 로스에 대해 신경 안쓰기 때문에 서버가 죽었는지 살았는지 신경 쓸 필요가 없기 때문입니다.
TCP인 경우 모든 데이터가 잘 전송 되어야 합니다. 서버가 연결이 죽어있다면 데이터를 잘 전송할 수 가 없습니다. 이럴 경우 연결을 아예 안맺는 게 낫습니다. 클라이언트 리소스가 낭비되기 때문이죠. 그래서 1차적으로 서버한테 원웨이를 하는 겁니다. SYNbit=1 > 너 연결 받아줄래?
서버가 ack을 받았다는 건 연결 받아줄 준비가 되어있다는 뜻입니다. 여기서 2way에서 끝난다면 SYNack(2번째 패킷)이 loss가 날 수 있습니다. 클라이언트는 서버가 죽었다고 오해할 수 있는 것이죠. 서버는 고스트서버가 됩니다. (서버는 리소스 다잡아두고 고스트 ㅠㅠ)
때문에 3way 핸드쉐이크로 안전하게 가는 겁니다.
연결을 끊을 때는 양쪽에서 끊는데요. UDP는 연결 끊는 절차도 없습니다.
TCP는 연결 안끊고 데이터만 발생 안시킨다면 리소스가 잡히기 때문에 안됩니다.(리소스 낭비) 정보를 관리하려고 저장해뒀기 때문이에요.
FINbit을 1로 셋팅하면 됩니다. ack을 통해 반응을 해주면서 FINbit을 교환하게 됩니다.
연결 끊는 것을 서버에게 허락받고, 서버에서도 연결 끊겠다는 것을 기다리고 양쪽 허용을 받으면 state정보를 날려버리고 끊습니다.
위처럼 각각 날릴 수도 있고 piggybacked해서 한 번에 날릴 수 있습니다 :)
'CS > 컴퓨터 네트워크' 카테고리의 다른 글
컴퓨터 네트워크 17일차 : Network layer (0) | 2021.11.03 |
---|---|
컴퓨터 네트워크 16일차 : TCP congestion control (0) | 2021.10.31 |
컴퓨터 네트워크 13일차 : TCP/IP, ACK time out 시퀀스넘버 (0) | 2021.10.13 |
컴퓨터 네트워크 12일차 : 소켓프로그래밍 멀티쓰레드 (0) | 2021.10.12 |
컴퓨터 네트워크 11-2일차 : 소켓프로그래밍 (0) | 2021.10.06 |