[네트워크] Connection-oriented transport: TCP

oldshoe·2024년 4월 23일

네트워크

목록 보기
18/34

TCP

TCP는 UDP와 상반된 프로토콜이다.
TCP는 handshaking을 통해 신뢰성을 보장하는 연결형 프로토콜이다.

TCP의 또다른 특징 중 하나는 데이터의 경계가 없다는 것이다.
예를 들어서 데이터를 100비트짜리 데이터를 2번 받았다고 할 때, 한 번에 200비트 데이터를 읽어오거나, 50비트씩 4번에 걸쳐 읽는 것도 가능하다.

TCP segment structure

일단 TCP는 UDP보다 보장하는 것이 많기 때문에 Header부터 복잡한 것이 많다.

TCP RTT와 time out 관계

RTT는 송신자가 데이터를 보내고 그에 대한 응답을 받을 때까지 걸리는 시간이다.
그 일정시간을 기다렸는데도 ACK를 받지 못하면 timeout을 발생시켜 재전송한다.

생각해보면, timeout 설정 시간은 RTT보다 짧게 설정하면 안된다. ACK가 오기 전에 timeout을 설정하면 불필요한 재전송이 많아진다. 이를 premature timeout이라고 하고, 너무 길게 설정하면 segment loss에 대한 빠른 대처가 어려워지고 성능이 저하된다.

그러면 어떻게 RTT를 예상하고 time out을 적절하게 설정할까?
sampleRTT와 estimatedRTT라는 변수들이 존재한다.
sampleRTT는 segment가 송신되고 ACK가 올 때까지의 시간, 즉 현재의 RTT이다.
estimateRTT는 지금가지 측정한 RTT들의 평균이다.

esitmatedRTT = (1-a)estimateRTT + a * sampleRTT

보통 a값은 0.125를 많이 사용한다.

그러면 timeout interval = Estimate + 4 * (sample - estimatedRTT) 가 된다.

restransmission scenarios

수신자에게서 ACK를 받고 나서야 sendbase를 증가시키는 것을 볼 수 있다.

두 개의 연속된 segment를 둘 다 잘 받았는데 첫 번째 segment에 대한 ACK가 유실되어도 cumulative ACK를 통해 timeout이 발생하지 않고 앞의 segment도 ACK를 받았다고 간주한다.
즉, 하나의 ACK로 여러 segment를 처리할 수 있는 장점이 있다.

TCP fast retransmit

timeout이 되기 전에 segment의 유실 여부를 판단하고 재전송할 수 있는 방법이 있다.
중복된 ACK를 여러 번 받는 것이다.

중복된 ACK가 3개 쌓이면 그 segment를 즉시 재전송한다.

TCP flow control

네트워크 계층이 데이터를 전송해주는 속도보다 응용 계층이 데이터를 처리하는 속도가 더 느리면 어떻게 해야하는가?

이전에 처리하는 속도보다 데이터가 쌓여가는 속도가 더 빠르면 큐가 계속해서 차고 packet loss가 발생한다.

그렇다면 보내는 쪽에서 상대방의 버퍼 현황을 보고 데이터를 전송해주는 속도를 조절하면 좋을 것 같다는 생각을 한다.

수신자는 자신의 버퍼 여유 공간을 송신자에게 알려 송신자가 데이터 전송 속도를 늦추게 할 수 있다. 그러면 수신자의 버퍼가 overflow 나지 않게 하여 packet loss를 막을 수 있다.

이 때 free buffer space를 rwnd라고 한다.
여유 공간 정보는 TCP segment의 receive window 부분에 명시되어 송신자에게 되돌아간다.

handshaking

TCP는 양방형 연결 지향형 프로토콜로서, 데이터의 교환 이전에 handshaking을 통해 연결을 수립한다.

연결을 수립하고 해제하는 과정을 handshaking이라고 한다.

두 호스트는 handshaking 과정을 통해 서로 연결되었음을 합의하는 것 뿐만 아니라 starting sequence number 또한 알 수 있다.(서로 간에 SYN 메시지로 특정 sequence number을 명시해서 보내고, 상대방은 이에 알았다는 뜻으로 +1 한 값을 ACK에 보낸다.)

2-way handshaking

보통의 상황에서는 문제가 없지만, A의 SYN에 대해 B의 ACK가 도달하기 전에 timeout이 발생하는 경우이다.
A가 seq 100으로 SYN을 보내서 B가 이에 대한 응답으로 ACK 101을 보냈는데, ACK가 도착하기 전에 A의 timeout 발동으로 인해 seq 200으로 다시 SYN을 보내는 상황이 발생했다. 이러면 A는 자신의 seq number가 200으로 바뀌었으니 101에 대한 ACK를 무시한다. 그리고 B가 생각하고 있는 A의 seq number와 실제 A가 다르게 되는 것이다.

그리고, B는 본인의 ACK가 잘 전송되었는지 알 수 없다.
B도 A에게 ACk를 보내야 양방향 통신에 대한 TCP의 신뢰성을 보장할 것이다.

3-way handshaking

그러면 마지막 A의 ACK도 필요할 것이다.
마지막 A의 ACK로서 끝나는 handshaking이 바로 완전한 연결을 수립할 것이다.

송신자를 보면 SYN를 보낸 직후에는 SYNSENT 상태가 된다. 그리고 ACK를 받으면 Established 상태가 되어 연결 준비를 마친다.

수신자는 SYN를 받기 전에는 listen 상태였다가, ACK를 보낸 후에는 SYN RCVD 상태가 되고, 본인의 ACK에 대한 상대방의 ACK를 받은 후에는 Established 상태가 되어 연결 준비를 마치게 된다.

profile
toomuxi : There are many things in the world that I want to do

0개의 댓글