쇠가죽 채찍! TCP에 대한 23 개의 어려운 문제를 직접 해결하는 기사!

오늘의 주제에 들어가기 전에 몇 가지 질문을하겠습니다.이 기사는 총 23 개의 질문을 제기합니다.

TCP 핸드 셰이크는 세 번이어야합니까? TCP는 네 번 흔들어야합니까?

빠른 재전송이 있고 시간 초과 재전송이 충분하지 않은 이유는 무엇입니까? SACK가있는 이유와 D-SACK이있는 이유는 무엇입니까?

우리 모두는 슬라이딩 윈도우가 있다는 것을 알고 있는데, 수신자가 너무 바빠서 슬라이딩 윈도우가 0으로 줄어들면 어떻게해야합니까? 보낸 사람이 영원히 기다리고 있습니까?

Silly Window는 무엇입니까?

슬라이딩 윈도우 흐름 제어에 혼잡 제어가 필요한 이유는 무엇입니까?

빠른 재전송은 3 개의 반복 된 ACK에 의존해야합니까?

이 기사에서는 문제에서 시작하여 TCP를 개발 및 진화의 관점에서 살펴 보는 대신 다양한 지식 포인트를 퉁명스럽게 이동하는 대신 TCP를 더 얕은 것에서 더 깊은 것으로 가고 싶습니다.

처음에는 컴퓨터 네트워크를 공부할 때 많은 질문이있었습니다. 내 마음은 10 만 개의 이유로 가득했고 네트워크는 매우 복잡했습니다. 오랜 세월의 개발 끝에 정말 너무 많은 것이 있습니다. 오늘은 대략적으로 말하고 있습니다. TCP의 이러한 점에 대한 나의 이해에 대해 알려주십시오.

좋아요, 더 이상 말도 안되는 얘기는하지 말고 요리를 시작하세요.

TCP는 어떤 문제를 해결하는 데 사용됩니까?

TCP는 전송 제어 프로토콜 (Transmission Control Protocol)의 약자로 전송 제어 프로토콜이라는 것을 알 수 있으며 초점은이 제어에 있습니다.

무엇을 제어해야합니까?

안정적이고 정돈 된 전송 및 종단 간 흐름 제어를 제어합니다. 충분한가? 충분하지 않습니다.보다 지능적이어야하므로 전체 네트워크에 대해 고려해야하는 혼잡 제어를 추가해야합니다.

이것은 당신과 나, 그리고 다른 사람들의 여정이며 안전은 모두에게 달려 있습니다.

TCP 및 IP 계층 제어가 충분하지 않은 이유는 무엇입니까?

우리는 네트워크가 계층으로 구현되고 네트워크 프로토콜이 통신용으로 설계되었음을 알고 있습니다. 실제로 링크 계층에서 IP 계층으로 통신이 완료 될 수 있습니다.

링크 레이어는 필수 불가결 한 것인데, 결국 우리 컴퓨터는 링크를 통해 서로 연결되고 IP는 주소 역할을하므로 IP를 통해 서로 통신 할 수 있습니다.

그렇다면 왜 TCP 계층을 추가합니까? IP 계층에 대한 제어가되지 않습니까?

제어를 위해 TCP 계층을 추출하는 이유는 IP 계층에 더 많은 장치가 포함되기 때문입니다. 데이터 조각은 네트워크에서 전송하기 위해 많은 장치를 통과해야하고 장치는 IP로 주소 지정되어야합니다.

IP 계층이 제어된다고 가정 할 때 관련 장비가 많은 것을 신경 써야합니까? 전체 전송 효율이 크게 저하됩니까?

예를 들어 A가 빌딩 블록을 F에게 전송하고 싶지만 직접 전송할 수없는 경우 B, C, D, E의 전송 스테이션을 통과해야합니다. 여기에는 두 가지 상황이 있습니다.

  • BCDE가 빌딩 블록이 틀렸는 지 여부를 신경 써야한다고 가정하고 패키지를 풀고 자세히 살펴보고 문제가 없으면 다시 넣고 마지막으로 F의 손에 닿습니다.

  • BCDE가 빌딩 블록에 신경 쓰지 않는다고 가정하면 패키지를 전달하면 끝납니다. 마지막 F는 빌딩 블록이 잘못되었는지 여부를 확인합니다.

어떤 종류의 효율성을 생각하십니까? 분명히 두 번째 유형입니다. 전달 장치는 이러한 것들을 신경 쓸 필요가 없습니다. 전달하기 만하면 완료됩니다!

따라서 제어 로직이 TCP 계층으로 분리되어 실제 수신자가 처리하도록하여 네트워크의 전체 전송 효율이 높습니다.

연결이란 정확히 무엇입니까?

우리는 이미 TCP 계층을 분리해야하는 이유와이 계층이 주로 사용되는 용도를 알고 있습니다. 어떻게 수행하는지 살펴 보겠습니다.

우리 모두는 TCP가 연결 지향적이라는 것을 알고 있습니다. 그렇다면이 연결은 무엇입니까? 끝과 끝을 연결하기 위해 정말로 선을 뽑았습니까?

소위 연결은 실제로 양 당사자가 상태를 유지하고 각 통신을 통해 상태의 변화가 유지되므로 서로 연결된 선이있는 것처럼 보입니다.

TCP 프로토콜 헤더

계속 진행하기 전에 매우 기본적이고 중요한 몇 가지 TCP 헤더 형식을 살펴볼 필요가 있습니다.

네트워크에서 가져온 사진

하나씩 설명하지 않고 요점에 집중합니다.

먼저 TCP 패킷에는 포트만 있고 IP는 없음을 알 수 있습니다.

Seq는 장애 문제를 해결하는 데 사용되는 Sequence Number입니다.

ACK는 Acknowledgment Numer로 패킷 손실 상황을 해결하고 보낸 사람에게 패킷을 수신했음을 알리는 데 사용됩니다.

플래그 비트는이 패킷의 유형을 표시하는 데 사용되는 TCP 플래그이며 TPC의 상태를 제어하는 ​​데 사용됩니다.

창은 흐름 제어에 사용되는 슬라이딩 창인 Sliding Window입니다.

세 악수

프로토콜 헤더의 요점을 명확히 한 후 3 방향 핸드 셰이크를 살펴 보겠습니다.

3 자 악수는 정말 흔한 질문이지만, 정말 이해하고 계십니까? 표면에 없나요? 다른 것을 확장 할 수 있습니까?

먼저 익숙한 과정을 살펴 보겠습니다.

네트워크에서 가져온 사진

먼저 핸드 셰이크가 필요한 이유는 주로 Seq Numer를 초기화하기위한 것입니다. SYN의 전체 이름은 Synchronize Sequence Numbers입니다.이 시퀀스 번호는 이후의 데이터 전송 순서를 보장하는 데 사용됩니다.

당신이 말하고 싶은 것은 양측의 송수신 기능이 정상인지 테스트하는 것인데 문제는 없다고 생각하지만 핵심은 일련 번호를 동기화하는 것입니다.

세 번인 이유는 저와 당신을 예로 들어 보겠습니다. 우선 제 초기 일련 번호를 알려드립니다. 당신은 그것을 듣고 받았다고 말했습니다.

그런 다음 귀하의 초기 일련 번호를 말하고 나는 그것을 받았다고 말합니다.

네 번 것 같나요? 정말 한 번 누르면 네 번이지만 중간 단계를 결합 할 수 있습니다. 즉, 내 초기 일련 번호를 알고 있다고 말하면 초기 일련 번호도 알려줍니다.

따라서 4 방향 핸드 셰이크를 3 개로 줄일 수 있습니다.

하지만 당신은 그런 상황에 대해 생각해 본 적이 없습니다. 당신과 나는 동시에 말하고 서로에게 초기 일련 번호를 말하고 따로 응답했습니다. 이건 4 자 악수 아닌가요?

더 명확하게 그림을 그려 보겠습니다.

4 방향 핸드 셰이크인지 확인 하시겠습니까?하지만 세부 사항은 여전히 ​​구현에 따라 다릅니다. 일부 구현에서는 이것이 발생하도록 허용하지 않을 수 있지만 핸드 셰이크의 초점은 동기화를 완료하는 초기 시퀀스 번호를 동기화하는 것이므로 우리의 생각에 영향을주지 않습니다. 목표.

초기 일련 번호 ISN의 값

ISN의 값을 무엇으로 설정해야하는지 생각해 보셨나요? 처음부터 시작하기 어려운 코드?

0과 같은 값을 쓰고 연결이 설정되고 클라이언트도 20 번째 패킷과 같은 많은 패킷을 보낸 다음 네트워크 연결이 끊어진 후 클라이언트가 다시 시작되고 포트 번호가 여전히 이전 번호이고 일련 번호가 있다고 가정합니다. 0부터 다시 시작하면 서버는 20 번째 패킷의 ack를 반환합니다 .. 클라이언트가 어리 석습니까?

따라서 RFC793은 ISN이 가짜 클럭에 바인딩되어야한다고 믿습니다. ISN은 4 마이크로 초마다 1 씩 증가합니다. 2의 32 제곱을 초과하면 다시 0부터 시작하여 ISN이 래핑하는 데 약 4 시간 30 분이 걸립니다.

따라서 ISN은 증분 값이되고 실제 구현에서는 불법 요소가 ISN을 추측하지 못하도록 임의의 값을 추가해야합니다.

SYN 시간 초과를 처리하는 방법은 무엇입니까?

즉, 클라이언트가 서버에 SYN을 보낸 후 멈춰 있는데 이때 서버가 SYN + ACK를 보내는데 응답이 없는데 어떻게해야하나요?

재 시도를 생각하고 있지만 연속해서 여러 번 재 시도 할 수는 없습니다. 생각해보십시오. 클라이언트가 오프라인 상태가되면 복구 할 시간을 주어야하므로 단계적으로 천천히 재 시도해야합니다. .

Linux에서 기본값은 5 회 재 시도이며 단계적 재 시도입니다. 간격은 1 초, 2 초, 4 초, 8 초, 16 초입니다. 5 번째 이후에는이 재 시도의 결과를 알기 위해 32 초를 기다려야합니다. 연결을 끊을 때까지 총 63 초를 기다린다고합니다.

SYN 홍수 공격

SYN 시간 초과가 없으면 서버 63의 연결이 끊어집니다. 즉, 서버는 63 초 내에이 리소스를 유지해야하므로 범죄자는 많은 클라이언트를 구성하여 SYN을 서버에 보낼 수 있지만 서버를 반환하지는 않습니다.

네트워크에서 가져온 사진

결과적으로 서버의 SYN 대기열이 고갈되고 정상적인 연결 요청을 처리 할 수 ​​없습니다.

그래서 뭘 할건데?

tcp_syncookies를 활성화하면 SYN 대기열이 사용되지 않습니다.

SYN 대기열이 가득 차면 TCP는 자신의 ip, 포트, 상대방의 ip, 포트, 상대방의 SYN 일련 번호, 타임 스탬프 및 기타 작업을 기반으로 특수 일련 번호 (예 : 쿠키)를 생성하여 특수 일련 번호 (예 : 쿠키)를 생성하고 다시 보냅니다. 상대방이 일반 클라이언트 인 경우 이 일련 번호를 다시 보내면 서버가이 일련 번호를 기반으로 연결을 설정합니다.

또는 tcp_synack_retries를 조정하여 재시도 횟수를 줄이고 tcp_max_syn_backlog를 설정하여 SYN 대기열 수를 늘리고 tcp_abort_on_overflow를 설정하여 SYN 대기열이 가득 차면 연결을 직접 거부합니다.

왜 네 번 흔들어?

네 개의 손과 세 개의 악수 쌍이 하나의 쌍을 이룹니다. 그것들은 TCP의 첫 번째 줄이기도합니다. 익숙한 그림을 다시 살펴 보겠습니다.

네트워크에서 가져온 사진

왜 네 번 손을 흔들어야합니까? TCP는 전이중 프로토콜이기 때문에, 즉 양 당사자가 닫혀 야하며 각 당사자는 FIN을 보내고 ACK를 상대방에게 응답합니다.

내 데이터가 끝났다고 말하고 답장을 보내면받는 것과 같습니다. 그런 다음 데이터가 끝났다고 말하고 답장을 보내서 받았습니다.

그래서 그것은 네 번처럼 보입니다.

그림에서 액티브 클로징 파티의 상태는 FIN_WAIT_1 ~ FIN_WAIT_2, TIME_WAIT, 패시브 클로징 파티는 CLOSE_WAIT ~ LAST_ACK임을 알 수 있습니다.

네 번 흔드는 상태가 이렇게 변해야하나요?

상태가 이렇게 바뀌어야합니까? 다른 사진을 봅시다.

네트워크에서 가져온 사진

양측이 능동적으로 연결 해제 요청을 시작하는 것을 볼 수 있으므로 각각이 활성 개시 자이며 상태는 FIN_WAIT_1에서 CLOSING의 전환 상태로 이동 한 다음 TIME_WAIT로 이동합니다.

네 번 흔들어야하나요?

클라이언트가 서버로 보낼 데이터가 없다고 가정하면 서버에 FIN을 전송하여 데이터 전송이 완료되었으며 더 이상 전송하지 않을 것임을 나타냅니다. 이때 서버에 클라이언트로 전송할 데이터가 아직 남아 있으면 먼저 ack 응답을 한 다음 데이터를 계속 전송합니다.

서버 데이터가 전송 된 후 클라이언트에게 FIN을 전송하여 전송되었음을 알리고 클라이언트의 ACK를 기다립니다.이 경우 4 개의 핸드 웨이브가 있습니다.

따라서 클라이언트가 FIN을 서버에 보내고 서버에 데이터가 없으면 서버는 FIN과 함께 ACK를 클라이언트에 보낸 다음 클라이언트의 ACK를 기다릴 수 있으므로 세 번만 흔들리지 않습니까?

TIME_WAIT이 있어야하는 이유는 무엇입니까?

수신자로부터 FIN을 수신하고 ACK에 응답 한 후 Disconnect Initiator는 직접 CLOSED 상태로 들어 가지 않고 2MSL의 대기 시간으로 대기 웨이브를 수행합니다.

MSL은 Maximum Segment Lifetime, 즉 메시지의 가장 긴 생존 시간입니다. RFC 793에서 정의한 MSL 시간은 2 분입니다. Linux의 실제 구현은 30 초이므로 2MSL은 1 분입니다.

그렇다면 왜 2MSL을 기다릴까요?

  • 패시브 클로징 파티가 최종 ACK를받지 못할까 봐 걱정이됩니다. 네트워크상의 이유로 패시브 파티가 도착하지 않으면 다시 FIN을 보냅니다. 이때 액티브 클로징 파티가 이미 CLOSED 상태라면 어리석은 일 이니 잠시 기다려주십시오.

  • 연결이 즉시 끊어 지지만 연결이 재사용되었다고 가정합니다. 즉, 5- 튜플이 정확히 동일하고 시퀀스 번호가 여전히 적절한 범위에 있다고 가정합니다. 확률은 낮지 만 이론적으로는 가능하지만 새 연결이 닫힙니다. 연결 링크 일부 잔여 데이터는 위의 내용을 방해하므로 일부 잔여 데이터를 처리하는 데 일정 시간이 주어집니다.

2MSL을 기다리면 어떻게 되나요?

서버가 적극적으로 많은 수의 연결을 닫으면 많은 양의 리소스가 사용되며 리소스는 2MSL까지 해제되지 않습니다.

클라이언트가 적극적으로 많은 수의 연결을 닫으면 2MSL의 해당 포트가 모두 점유되고 65535 개의 포트만 있습니다. 포트가 모두 소진되면 연결을 시작할 수 없지만 가능성이 매우 낮다고 생각합니다. 포트 몇 개의 연결을 설정 하시겠습니까?

2MSL로 인한 문제를 해결하는 방법은 무엇입니까?

빠른 재활용, 즉 2MSL을 기다리지 않고 재활용합니다. Linux의 매개 변수는 tcp_tw_recycle이고 tcp_timestamps는 기본적으로 활성화되어 있습니다.

사실 위의 2MSL을 기다려야하는 이유를 이미 분석 했으므로 대기 시간이 결정적이라면 위에서 언급 한 문제가 발생할 것입니다.

따라서 여는 것은 권장하지 않으며이 매개 변수는 Linux 4.12 버전 이후에 클릭되었습니다.

얼마 전에 한 친구가 그룹에서이 내용을 언급했습니다.

내가 물었을 때 NAT가 거기에있었습니다.

요청한 쪽이 서버의 정적 자원을 요청하고 가끔 20 ~ 60 초 정도에 응답이 발생하는 현상으로, 패킷 캡처에서 요청한 쪽은 3 개의 연속 SYN에 대해 응답하지 않습니다.

예를 들어, 학교에있는 경우 공용 네트워크 IP가있는 경우 tcp_tw_recycle을 켠 다음 (tcp_timestamps도 켜진 경우) 60 초 이내에 동일한 IP에 대한 연결 요청에서 타임 스탬프를 증가시켜야합니다. 그렇지 않으면 만료 된 것으로 간주됩니다. 패킷이 삭제됩니다.

학교에 기계가 너무 많으면 타임 스탬프가 일관 적이라고 보장 할 수 없으므로 문제가 발생합니다.

그래서 이것은 권장되지 않습니다.

재사용, 즉 tcp_tw_reuse를 켜려면 tcp_timestamps도 필요합니다.

여기서 중요한 점이 있는데, tcp_tw_reuse는 연결 개시 자로 사용되며 우리 서버는 기본적으로 수동 수신기에 연결됩니다.

새로운 연결이 시작되면 tcp_tw_reuse는 TIME_WAIT 상태의 연결을 1 초 이상 재사용 할 수 있으므로 서버의 부담을 전혀 줄이지 않습니다.

TIME_WAIT에서 이니시에이터의 연결을 재사용합니다.

일부 사람들이 tcp_tw_reuse와 혼동 할 수있는 SO_REUSEADDR도 있습니다. 첫째, tcp_tw_reuse는 커널 옵션이고 SO_REUSEADDR은 사용자 모드 옵션입니다.

그러면 SO_REUSEADDR이 주로 서비스 시작시 사용됩니다. 이때 포트가 점유되고 연결이 TIME_WAIT 상태이면이 포트를 재사용 할 수 있습니다. TIME_WAIT가 아닌 경우 이미 사용중인 주소를 제공합니다.

그래서이 두 가지가 작동하지 않는 것 같고, tcp_tw_reuse와 tcp_tw_recycle은 실제로 TCP 프로토콜을 위반합니다. 예라고 말하면 늙 으면 몰래 놓아 주나요?

MSL 시간을 줄이지 만 안전하지 않거나 tcp_max_tw_buckets를 조정하여 TIME_WAIT 수를 제어하지만 기본값은 이미 180,000만큼 매우 큽니다.이 방법은 DDos 공격에 대응하는 데 사용해야합니다.

그래서 내 제안은 서버가 능동적으로 종료되어서는 안되며 클라이언트에 활성 종료 파티를 두는 것입니다. 결국 우리 서버는 일대 다 서비스이며 우리의 리소스는 더 소중합니다.

자신을 공격하십시오

또한 매우 부끄러운 해결책이 있는데, 제가 생각했던 것은 제 자신을 공격하는 것이 었습니다.

소켓에는 비 로컬 주소를 바인딩 할 수있는 IP_TRANSPARENT라는 옵션이 있습니다. 그러면 서버가 연결의 IP와 포트를 기록합니다 (예 : 로컬 위치에 기록).

그런 다음 서비스를 시작합니다. 서버의 리소스가 부족하면 일정 시간을 설정할 수 있습니다. 오랜 시간이 지나면 TIME_WAIT 상태에서 상대방의 IP 및 포트에 대해 서비스에 알려줍니다.

그런 다음 서비스는 IP_TRANSPARENT를 사용하여 이전 클라이언트 인 것처럼 가장하여 서버에 요청을 시작한 다음 서버는 실제 클라이언트에 ACK를 전송합니다. 클라이언트는 닫히고 수행중인 작업을 말하므로 RST를 반환합니다. , 그리고 서버는 연결을 종료합니다.

타임 아웃 재전송 메커니즘은 어떤 문제를 해결합니까?

앞서 TCP는 신뢰할 수있는 전송을 제공해야하고 네트워크가 불안정하다고 언급 한 바 있는데, 전송 된 패킷이 상대방에 의해 수신되지 않고 신뢰성이 보장되어야한다면 재전송을해야합니다.

TCP의 신뢰성은 확인 번호에 따라 달라집니다. 예를 들어 1, 2, 3, 4 개의 패킷 4 개를 보내면 지금 5 개를 원한다고하면 처음 4 개의 패킷을 받았다는 의미입니다. .

그러나 여기서 SeqNum과 ACK는 모두 바이트 수에 포함되어 있습니다. 즉, 1, 2, 4를 받았지만 3을받지 않고 5를 ACK 할 수 없다고 가정합니다. 5를 반환하면 보낸 사람은 다음과 같이 생각합니다. 5 이전에 모든 것을 받았습니다

따라서 최대 연속 수신 패킷 인 3 개만 응답 할 수 있습니다.

발신자는 2 개의 패킷 3과 4가 아직 도착하지 않았는지 또는 분실되었는지 확실하지 않으므로 발신자는 대기해야하며 대기 시간은 더 구체적입니다.

너무 조급하면 ACK가 이미 이동 중일 수 있으며 재전송은 자원 낭비입니다. 너무 엉성하면 수신자가 불안합니다.이 죽은 사람은 왜 소포를 보내지 않았습니까? 기다린 모든 꽃에 감사드립니다.

그래서 시간이 지남에 따라 재전송을 기다리는 시간이 매우 중요합니다. 어떻게해야할까요? 똑똑한 친구들이 바로 생각해봤을지도 모르겠네요. 평소처럼왔다 갔다하는 데 걸리는 시간을 추정 할 수 있습니다. 너무 오래 기다렸습니다.

이 왕복 시간을 RTT, 즉 Round Trip Time이라고하며,이 시간에 따라 시간에 따른 재전송을위한 RTO 시간, 즉 Retransmission Timeout이 설정됩니다.

그러나 RTO에 대해 RTT를 참조하는 것 외에 선택의 여지가 없지만 어떻게 계산할 수 있습니까? 우선, 그것은 샘플링이어야하고, 가중 평균의 물결이 RTO를 얻을 것입니다.

RFC793에 의해 정의 된 공식은 다음과 같습니다.

1 、 先 采样 RTT 2 、 SRTT = (ALPHA * SRTT) + ((1-ALPHA) * RTT) 3 、 RTO = min [UBOUND, max [LBOUND, (BETA * SRTT)]]

ALPHA는 0.8과 0.9 사이의 값을 가진 평활 계수이고, UBOUND는 시간 제한 시간 -1 분의 상한, LBOUND는 하한 -1 초, BETA는 1.3과 2.0 사이의 값을 가진 지연 분산 계수입니다.

하지만 여전히 문제가 있는데, RTT 샘플링 시간은 데이터 전송 시작부터 ACK 수신까지의 시간을 샘플 값으로 사용하거나 재전송 시간부터 ACK 시간까지의 시간을 샘플 값으로 사용합니까?

네트워크에서 가져온 사진

그림에서 알 수 있듯이 한 번은 길고 한 번은 짧다고하는데, ACK가 누구에게 답장하는지 모르기 때문에 조금 어렵습니다.

그래서 뭘 할건데? 재전송의 앞뒤를 샘플링하고 싶지 않습니다. 누가이 ACK에 응답하는지 모르겠습니다. 신경 쓰지 않고 정상을 앞뒤로 샘플링합니다.

이것은 Karn / Partridge 알고리즘, 샘플링 및 재전송이없는 RTT입니다.

하지만 샘플링없이 재전송하는 데 문제가있을 수 있습니다. 예를 들어 특정 순간에 네트워크가 갑자기 나빠집니다. 재전송을 신경 쓰지 않으면 정상 RTT에 따라 RTO를 계산하면 타임 아웃 기간이 너무 짧아서 네트워크가 매우 열악합니다. 이 경우 미친 재전송은 네트워크의 부하를 증가시킵니다.

따라서 Karn 알고리즘은 재전송을 매우 무례합니다. 현재 RTO를 두 배로 늘릴 것입니다. 그렇게 간단하고 무례합니다.

그러나 이런 종류의 평균 계산은 갑작스러운 큰 변동을 완화하기가 쉽기 때문에 또 다른 알고리즘은 Jacobson / Karels 알고리즘이라고합니다.

최신 RTT를 계산하고 적절한 RTO를 얻기 위해 SRTT를 매끄럽게합니다. 공식을 게시하지 않을 것입니다. 어쨌든 이해가되지 않습니다. 이해가 안된다면 경고음이 울리지 않습니다.

빠른 재전송 메커니즘이 필요한 이유는 무엇입니까?

타임 아웃 재전송은 시간에 따라 이루어지며, 네트워크 상태가 정말 나쁘면 타임 아웃 재전송은 괜찮지 만 네트워크 상태가 좋으면 패킷 손실 일 뿐이므로 오래 기다릴 필요가 없습니다.

데이터 기반 재전송을 고속 재전송이라고합니다. 무슨 의미일까요? 즉, 발신자가 상대방으로부터 3 회 연속으로 동일한 확인 번호를 받으면 데이터가 즉시 재전송됩니다.

현재 네트워크 상태가 정상임을 증명하기 위해 동일한 ACK를 연속 3 회 수신하므로 패킷 손실이 확인되어 즉시 재전송되므로 오래 기다릴 필요가 없습니다.

네트워크에서 가져온 사진

완벽 해 보이지만 1, 2, 3, 4 개의 패킷 4 개를 보냈는데 상대방이 2 개 패킷을받지 못하고 1, 3, 4 개를 받았는데 타임 아웃 재전송이든 빠르 든 상관 없습니다. 어쨌든 상대방은 ACK 2를 반환합니다.

이때 2, 3, 4 또는 2 만 재전송해야합니까?

해결해야 할 SACK 도입은 어떤 문제입니까?

SACK는 Selective Acknowledgment로 어떤 데이터를 재전송해야하는지 발신자가 모르는 문제를 해결하기 위해 도입되었습니다.

아래 그림을 보시죠.

네트워크에서 가져온 사진

SACK는 수신자가 수신 한 데이터를 다시 전송하여 상대방이 어떤 데이터를 수신했는지 알 수 있으므로 누락 된 데이터를 선택적으로 전송할 수 있음을 의미합니다.

그림과 같이 5500 데이터로 시작하고 SACK를 계속 업데이트하고 싶다고 ACK로부터 알 렸습니다. 6000-6500 수신, 6000-7000 데이터 수신, 6000-7500 데이터 수신, 발신자는 매우 명확합니다. 5500-5999의 데이터 웨이브가 손실되어야한다는 것을 알고 재전송되었습니다.

그리고 데이터가 여러 불연속적인 경우 SACK 0-500, 1000-1500, 2000-2500과 같은 SACK도 보낼 수 있습니다. 이 단락이 수신되었음을 의미합니다.

D-SACK은 무엇입니까?

D-SACK은 실제로 SACK의 확장입니다. SACK의 첫 번째 문단을 사용하여 반복적으로 수신되는 불연속 데이터 시퀀스 번호를 설명합니다. 첫 번째 문단에서 설명한 범위가 ACK에 포함되면 반복됨을 의미합니다. 예를 들어, ACK는 6000입니다. SACK 5000-5500을 돌려 주시겠습니까?

솔직히 말하면 첫 단락의 피드백에서받은 ACK를 비교하는 것으로, 매개 변수는 tcp_dsack으로 Linux 2.4 이후에 기본적으로 활성화됩니다.

반복하는 것을 앎의 소용은 무엇입니까?

1. 반복되는 것을 안다는 것은 상대방이 방금 패킷을 수신했음을 의미하므로 반환 된 ACK 패킷은 손실됩니다. 2. 패키지가 고장 났는데 처음 보낸 패키지가 나중에 도착합니까? 3. 당신은 너무 불안하고 RTO가 너무 작습니까? 4. 데이터에 의해 복사되고 한 발 앞서 있습니까?

슬라이딩 윈도우를 사용하는 이유는 무엇입니까?

우리는 TCP가 시퀀스 번호와 재전송을 가지고 있다는 것을 이미 알고 있지만 이것으로는 충분하지 않습니다. 우리는 놀라지 않기 때문에 네트워크가 복잡하고 변경 가능하며 때로는 차단되기 때문에 상황에 따라 전송 속도를 제어해야합니다. , 때로는 매우 부드럽습니다.

따라서 발신자는 수신자의 상황을 알 필요가있어 송신 속도를 제어하여 맹목적으로 송신하지 않고 수신자가이를 수락 할 수 없습니다.

따라서 TCP에는 흐름 제어를위한 슬라이딩 윈도우라는 것이 있습니다. 즉, 수신자는 내가받을 수있는 데이터의 양을 보낸 사람에게 알려주고 보낸 사람은이 정보를 기반으로 데이터를 보낼 수 있습니다.

다음은 발신자가 관리하는 창으로 검은 색 원으로 표시됩니다.

네트워크에서 가져온 사진

그림에서 # 1은 ACK를받은 데이터, # 2는 ACK를 받았지만 ACK를받지 못한 데이터, # 3은 창에서 보낼 수 있지만 아직 보내지 않은 데이터입니다. # 4는 아직 보낼 수없는 데이터입니다.

이때 36-51 ACK가 수신되었고 46-51 바이트가 전송되었으므로 창이 오른쪽으로 미끄러졌습니다.

인터넷의 사진

TCP / IP 가이드에도 전체 그림이 있는데 이는 매우 분명합니다.

수신자의 응답 창이 항상 0이면 어떻게됩니까?

위에서 언급했듯이 송신 방법은 수신자의 응답 창에 따라 전송할 수있는 데이터의 양을 제어하는데 수신자가 0으로 계속 응답하면 발신자가 멈춘 것입니까?

생각해보세요. 발신자가 보낸 데이터는 ACK 된 것이지만 응답 창은 0입니다. 발신자는이 시점에서 보내는 것이 두려워서 영원히 기다릴 수 없습니다. 창은 언제 0으로 유지됩니까? ?

그래서 TCP는 Zero Window Probe 기술을 가지고 있는데, 발신자가 윈도우가 0이라는 것을 알고 나면 수신자가 정상인지, 즉 ZWP 패킷을 수신자에게 보냅니다.

구현을 자세히 살펴보고 여러 번 보낼 수 있고 간격이 있고 여러 번 후에 직접 RST를 할 수 있습니다.

수신자가 매번 매우 작은 창으로 응답한다고 가정 해 보겠습니다.

수신자가 매번 1 바이트를받을 수 있다고 말한다면 발신자가 보내야합니까?

TCP + IP 헤더는 40 바이트에 불과하며이 전송은 비용 효율적이지 않으며 계속해서 멍청하게 보내면 바보 창이라고합니다.

무엇을해야할지 생각해 보면 발신자는 기다렸다가 비육이 다시 보낼 때까지 기다리거나 수신자는 의식적으로 데이터가 임계 값보다 작으며이 시점에서 창이 0임을 발신자에게 알립니다. 종료.

발신자가 기다리고있는 해결책은 Nag 알고리즘인데,이 알고리즘은 코드 만 봐도 알 수 있다고 생각합니다.

간단히 말해서 현재 보낼 수있는 데이터와 윈도우는 MSS보다 크거나 같고 즉시 보내지 않으면 이전에 보낸 패킷의 ACK가 돌아 왔는지 판단하여 다시 보내거나 데이터를 저장합니다.

수신자의 의식적인 솔루션은 David D Clark의 솔루션입니다. 윈도우 데이터가 특정 임계 값보다 작 으면 송신자 윈도우 0에게 보내지 말라고 알리고 데이터가 MSS보다 크거나 같을 때까지 기다리거나 버퍼를 수락하여 공간의 절반을 확보 한 다음 일반 윈도우 값을 다음과 같이 설정하십시오. 송신기.

그건 그렇고, Nag 알고리즘은 지연 확인을 언급해야합니다 .Nag 알고리즘은 수신자의 확인을 기다리고 있으며 지연 확인을 켜면 확인 전송이 지연됩니다. 후속 패킷이 수신 될 때까지 기다린 다음 함께 확인하거나 잠시 기다립니다. 정보가 사라 졌는지 확인하기 위해 응답하십시오.

이것은 서로를 기다린 다음 지연이 매우 커서 두 가지를 동시에 켤 수 없습니다.

슬라이딩 윈도우가있을 때 혼잡 제어가있는 이유는 무엇입니까?

앞서 말씀 드렸듯이 TCP는 양측의 상황뿐만 아니라 전체적인 네트워크 상황을 알아야하기 때문에 혼잡 제어가 추가되었습니다. 결국 모든 사람이 규칙을 지키면 길은 순조 로울 것입니다.

앞서 재전송에 대해 언급했는데 네트워크의 전반적인 상황에 관계없이 상대방이 ACK를주지 않았다면 생각없이 재전송을하겠다.

이때 네트워크 상태가 매우 나쁘고 모든 연결이 무심코 이렇게 재전송된다면 네트워크 상태가 더 나 빠지고 혼잡할까요?

그러면 혼잡이 많을수록 재전송이 많아지고 계속 서두르십시오! 그럼 GG입니다.

따라서 이러한 상황에서 전송을 방지하려면 혼잡 제어가 필요합니다.

혼잡 제어는 어떻게하나요?

주로 다음 단계가 있습니다.

1. 천천히 시작하고 길을 탐색하십시오. 2. 혼잡 회피, 거의 느려진 느낌 3. 혼잡 발생 빠른 재전송 / 복구

느린 시작은 새 드라이버가 도로에서 천천히 시작하고 cwnd (Congestion Window)를 1로 초기화 한 다음 ACK를받을 때마다 cwnd ++를 초기화하고 RTT가 통과 할 때마다 cwnd = 2 * cwnd를 의미합니다.

선형성에 지수가 있고 지수가 선형 적으로 증가합니다.

그런 다음 임계 값, 즉 ssthresh (저속 시작 임계 값)에 도달하면 혼잡 회피 단계로 들어갑니다.

이 단계에서 ACK가 수신되고 모든 RTT가 cwnd ++ 일 때마다 cwnd = cwnd + 1 / cwnd입니다.

모두 선형 적으로 증가하는 것을 볼 수 있습니다.

이후 패킷 손실이 발생할 때까지 계속 증가하며 재전송에는 타임 아웃 재전송과 빠른 재전송의 두 가지 유형이있는 것으로 분석되었습니다.

시간 초과 재전송이 발생하면 상황이 약간 나쁘다는 것을 의미하므로 ssthresh를 현재 cwnd의 절반으로 직접 설정 한 다음 cwnd가 직접 1로 변경되어 느린 시작 단계로 들어갑니다.

빠른 재전송 인 경우 두 가지 구현이 있습니다. 하나는 시간 초과 재전송과 동일하게 처리하는 TCP Tahoe입니다.

하나는 TCP Reno입니다.이 구현은 cwnd = cwnd / 2를 설정 한 다음 ssthresh를 현재 cwnd로 설정하는 것입니다.

그런 다음 빠른 복구 단계에 들어가서 cwnd = cwnd + 3을 설정하고 (3 개의 빠른 재전송이 있기 때문에) DACK에 지정된 패킷을 재전송하고, 다른 DACK를 수신하면 cwnd ++, 정상 ACK를 수신하면 cwnd를 다음으로 설정합니다. ssthresh 크기, 혼잡 회피 단계로 들어갑니다.

빠른 복구 후 지정된 패킷이 재전송 된 것을 확인할 수 있습니다. 많은 패킷이 손실 된 후 다른 패킷은 타임 아웃이 재전송 될 때까지만 기다릴 수 있습니다. 타임 아웃 재전송은 cwnd를 반으로 줄이며 여러 번 트리거하면 기하 급수적으로 증가합니다. 레벨이 떨어집니다.

그래서 New Reno를 만들고 New를 추가했습니다. SACK없이 빠른 복구를 향상시키기위한 것입니다. DACK에서 지정한 패킷의 응답 ACK가 전송 된 가장 큰 ACK인지 관찰합니다. , 2, 3, 4, 상대방은 2를받지 못했지만 3, 4는 수신되었으므로 2를 재전송 한 후 ACK는 5 여야하며이 패킷이 손실되었음을 나타냅니다.

그렇지 않으면 손실 된 다른 패킷이 있습니다. 하나의 패킷이 손실되면 프로세스는 이전과 동일합니다. 다른 패킷이 손실 된 경우 ACK가 모두 될 때까지 재전송을 계속 한 다음 빠른 복구 단계를 종료합니다.

간단히 말해,이 링크를 종료하기 전에 모든 패킷이 수신 된 것으로 감지되었습니다.

또한 재전송 과정에서 혼잡 제어로 SACK를 기반으로하는 FACK도 있는데, 위의 New Reno와 비교하면 SACK가 있다는 것을 알고 있으므로 하나씩 시도 할 필요가 없으니 자세한 설명은하지 않겠습니다.

다른 혼잡 제어 알고리즘은 무엇입니까?

위키에는 너무 많습니다.

원래는 몇 마디 만 삑삑 거리다가 삑 삑삑 삑삑 삑삑 삑삑 삑삑 대는 소리를들은 후 지 웠어요. 말하지 않은 것과 똑같다고 느꼈어요. 더 깊이 들어가고 싶었지만 힘이 허락하지 않았어요. 약간 우울했습니다.

여러분, 직접 확인 하시거나 제 재배에 성공할 때까지 기다렸다가 다시 오세요.

요약하자면

너무 많이 말 했으니 요약하자.

TCP는 연결 지향적이며 안정적이고 질서있는 전송을 제공하고 흐름 제어 및 혼잡 제어를 제공합니다 .TCP 계층은 IP 계층에서 사용할 장치가 더 많아 복잡한 논리를 추가하기 때문에 IP 계층에서 구현되지 않고 별도로 추출됩니다. 비용 효율적이지 않습니다.

3 방향 핸드 셰이크는 주로 후속 전송의 기반을 마련하기 위해 초기 시퀀스 번호를 정의하는 것이며, 네 개의 손은 TCP가 전이중 프로토콜이기 때문에 양측 모두 작별 인사를해야합니다.

SYN 시간이 초과되면 단계적으로 재 시도합니다. SYN 공격이있는 경우 대기열 수를 절반으로 늘리거나 재시도 횟수를 줄이거 나 단순히 거부 할 수 있습니다.

TIME_WAIT는 상대방이 마지막 ACK를받지 못한 다음 FIN을 보냈 을까 두려워하며 새로운 연결에 영향을 미칠 까봐 네트워크에 남아있는 데이터를 처리하기를 기다리고 있습니다.

TIME_WAIT는 작거나 TIME_WAIT 메커니즘을 파괴하는 데 권장되지 않습니다. 정말로 원한다면 빠른 복구 또는 재사용을 설정할 수 있지만 이점에주의하십시오.

타임 아웃 재전송은 상대방이 패킷을 수신 할 수 있도록하기위한 것이며, 빠른 재전송은 패킷이 가끔 손실 될 때 이러한 긴 타임 아웃을 기다릴 필요가 없도록하는 것이며, SACK는 송신자에게 재전송을 알리는 것입니다.

D-SACK은이 재전송의 이유가 상대방이 실제로 수신하지 않았거나 너무 성급하다는 것을 발신자에게 알리는 것입니다. RTO가 너무 작아서 그의 눈이 검게되지 않을 것입니다.

슬라이딩 윈도우는 발신자의 발신 율과 수신자의 수신율의 균형을 맞추기위한 것으로 맹목적으로 발송하지 않도록합니다. 물론 Silly Window에주의를 기울여야합니다. 동시에 Nag 알고리즘에도주의를 기울여야하며 지연 확인은 함께 사용할 수 없습니다.

슬라이딩 윈도우는 충분하지 않습니다. 혼잡 제어가 있어야합니다. 당신과 나, 안전은 모든 사람에게 달려 있기 때문에 TCP는 뛰어 내려 현재 상황을 봐야합니다.

마침내

이 시점에서 거의 똑같지 만 여전히 많은 세부 사항이 있습니다 .TCP 프로토콜이 너무 복잡합니다. 이것은 내 기사에서 가장 적게 묘사 될 수 있습니다. 내 그림을 그리기에는 너무 복잡하다는 것을 알 수 있습니다. hahaha.

오늘은 방금 말씀 드렸는데, 실수가 있으면 최대한 빨리 무대 뒤에서 연락주세요.

추천

출처blog.csdn.net/sinat_37903468/article/details/108586639