가자미의 개발이야기

[네트워크] TCP(rdt, flow control, connection management) 본문

Computer Science/네트워크

[네트워크] TCP(rdt, flow control, connection management)

가자미 2021. 4. 16. 19:23

a. TCP의 rdt(신뢰성 있는 데이터 전송)

TCP는 ip의 위에서 rdt 서비스를 제공한다.(ip는 신뢰성 없음)

-pipelined 방식 사용(gbn selective 선택 사용)

-cumulative ack(누적 ack 방식 사용)

-보냈는데 ack를 받지 못한 패캣에 해당하는 타이머 하나를 운용

 

b. TCP sender

 

초기에 NextSeqNum과 SendBase를 초기화.

 

상위 계층이 데이터 전송을 요구할 때,

nextseqnum에 해당 되는 데이터를 세그먼트 생성하고,

nextseqnum을 생성된 데이터 만큼 뒤로 보내고 타이머 실행.

 

타이머가 다 되면,

보냈는데 ack를 못받은 데이터 중 시퀀스 넘버가 가장 작은 놈을 다시 보내고 타이머 재시작.

 

ack를 받으면 sendbase를 ack까지 옮김

만약 아직 받지 못한 ack가 있다면 타이머를 시작하고 그렇지 않으면 타이머 종료

 

c. TCP ack generation

event at receiver TCP receiver action
예상한 패캣이 오고 해당 패캣 이전까지는 ack 보냈음 혹시 다른 패캣이 올지 모르니 500ms 기다린 후 안오면 해당 ack를 보냄.
예상한 패캣이 왔는데 해당 패캣 이전에 ack를 안보낸 패캣이 있음 즉시 cumulative ack(누적ack)를 보냄
예상한 패캣보다 시퀀스 번호가 큰 패캣이 온 경우(gap detected) 바로 중복된 ack를 보냄.(지금까지 잘 받은 ack, 리시버가 기다리는 시퀀스 넘버이기도.)
갭을 채우는 패캣이 왔을때 바로 해당 ack를 보냄

d. TCP fast retransmit

타이머가 커질 수록 재전송할 때까지 기다리는 시간이 길어지게 된다.

=>이런 시간을 줄이려는게 fast retransmit

 

센더가 여러 세그먼트를 계속해서 보낼 때,

만약 어떤 세그먼트가 없을 경우 리시버는 동일한 ack를 중복해서 계속 보내게 된다.

이럴 경우 센더가 세번의 중복 ack를 받을 경우

타이머를 기다리지 않고 ack를 받지 못한 시퀀스번호가 가장 작은 세그먼트를 바로 재전송한다.

 

e. TCP flow control

센더가 보내는 양이 리시버가 처리하는 양보다 너무 많으면

이를 조절하는 기능

 

리시버는 헤더의 receiver window라는 곳에 현재 TCP 리시버 버퍼(RcvBuffer)에

남은 공간(rwnd)이 얼마나 있는지를 작성해서 ack에 담아 전송함.

남은 공간=리시버 버퍼-(받는 속도-처리 속도)

 

e. TCP connection management

리시버와 센더가 서로간의 상태정보(초기 시퀀스넘버, 센더버퍼 사이즈, 리시버버퍼 사이즈)를 연결을 시작할 때 서로 교환

 

하지만 TCP는 2way handshaking을 사용하지 않음

=> 응답을 보내고 대답을 듣는 시간이 가변적임.

리시버의 재전송시간이 센더의 타이머보다 늦다보니, 센더가 연결 요청을 다시보내게 되고,

다시 보내게 된 연결에 따라 data를 전송하게 된다.(x를 보내야 되는데 x+1을 보내게 됨)

이렇게 데이터를 전송한 이후 연결을 닫으면 재전송한 연결요청의 답을 들을 수 없게 된다.

 

그래서 TCP는 3way handshaking을 함

헤더에 있는 syn을 통해 연결 유무를 판단하고, 양방향 연결을 함.(x,y는 임의의 값)

이때 acknum=x+1은 비록 연결요청에는 데이터 값이 없지만, 요청 자체가 1비트라고 여겨서 acknum에 +1된것.

 

3 way handshaking은 연결을 닫을 때도 특이하다.

클라이언트가 먼저 연결을 종료한다고 가정한 상황이다.

헤더에 있는 fin을 활용해 연결 종료 의사를 밝힌다.

이것이 전달되면 서버도 ack를 통해 클라이언트의 연결 종료 의사를 확인한다.

(이때 중요한 건 서버 쪽은 연결을 종료하지 않았다는 것이다. 단지 클라이언트가 연결, 즉 전송을 종료했을 뿐이다.)

그리고 마지막으로 서버도 종료 의사를 전달하여 클라이언트가 받았을 때 클라이언트는 잠시동안 대기한다.

왜냐면 클라이언트가 보낸 종료ack가 서버에 잘 전달 안됐을 수 있기 때문이다.

(잘 전달되지 않으면 서버는 종료의사를 다시 재전송하게 된다.)