nếu một gói TCP được xác nhận một phần, cơ chế truyền lại sẽ phản ứng như thế nào?


12

nếu một máy khách tcp gửi một gói, với số thứ tự từ 10000 đến 20000, đến một máy chủ tcp. tcp sẽ trả lời bằng ACK với seq_ack 20001.

nếu tôi chặn gói TCP từ máy khách và chia gói thành 2 phân đoạn tcp, một phân đoạn có seq từ 10000 đến 15000 và phân đoạn khác có seq từ 15001 đến 20000. Sau đó, 2 phân đoạn TCP này được gửi đến máy chủ TCP. Giả sử rằng đoạn thứ hai bị mất trong đường dẫn. Máy chủ TCP sẽ phản hồi ACK với seq_ack 15001.

Bây giờ, vì máy khách TCP gửi một gói tích hợp với seq 10000 đến 20000, nhưng nó nhận được ACK với 15001, theo quan điểm của khách hàng, điều này thật kỳ lạ. Nó sẽ phản ứng thế nào? Về lý thuyết, máy khách nên truyền lại các byte từ seq 15001 đến 20000, cụ thể là máy khách sẽ truyền các gói mới từ seq 15001. Nhưng thực tế, trong thực thi ngăn xếp TCP, có giống như trong lý thuyết không?

Tôi nghĩ trong bộ đệm gửi TCP, khi một phân đoạn tcp được gửi, phân đoạn đó vẫn ở đó cho đến khi ACK. Khi ACK đến, các byte cho phân đoạn sẽ bị xóa khỏi bộ đệm. Có một con trỏ trong bộ đệm gửi, khi ACK đến, con trỏ trỏ đến vị trí mà ack_seq tương ứng. Các byte nằm dưới ack_seq sẽ bị xóa. Theo cách này, toàn bộ phân khúc không cần phải truyền lại?

Câu trả lời:


8

Đây được gọi là xác nhận chọn lọc và đã được bao gồm trong đặc tả TCP được xác định trong RFC 2018 . Điều này sẽ cho phép máy khách thực sự gửi lại chỉ byte 15001 đến 20000 (vì chúng nằm trong các gói / phân đoạn khác nhau nếu bạn đã tách chúng như bạn nói), nhưng thú vị hơn, nó thậm chí còn cho phép các xác nhận không theo thứ tự.

Từ RFC 2018:

Khi nhận được ACK chứa tùy chọn SACK, người gửi dữ liệu NÊN ghi lại xác nhận chọn lọc để tham khảo trong tương lai. Người gửi dữ liệu được giả sử có hàng đợi truyền lại có chứa các phân đoạn đã được truyền nhưng chưa được xác nhận, theo thứ tự số thứ tự.

Hỗ trợ SACKkhông cần thiết bởi các đặc điểm kỹ thuật TCP. Nếu máy khách hoặc máy chủ không hỗ trợ xác nhận chọn lọc, thực sự tất cả các byte 10000 đến 20000 sẽ phải được truyền lại.

Trong triển khai ngăn xếp TCP, nó có giống như trong lý thuyết không?

Thường SACK được hỗ trợ, vì hiệu suất, hiệu quả và độ trễ tăng đáng kể - đặc biệt là trong một mạng như internet.

Tuy nhiên, thực tế, những giả định này sẽ đúng ngay cả khi bạn thao tác thủ công các gói như bạn đã nêu. Theo RFC 793 , tối thiểu, toàn bộ cửa sổ dữ liệu sẽ phải được truyền lại, nhưng người nhận lại biết rằng dữ liệu nhận được ít nhất là hợp lệ . Để biết chi tiết thực hiện, Phần 3.3 - Số thứ tự từ RFC 793.

Để biết một phác thảo của toàn bộ quá trình cả có và không có hỗ trợ xác nhận có chọn lọc, hãy xem bài viết này (bao gồm một số sơ đồ rất hữu ích).


nó hơi lạ đối với tôi, vì TCP là giao thức hướng byte, dựa trên luồng. Tại sao nó phải truyền lại toàn bộ phân khúc? Dường như với tôi, TCP không có SAKC là giao thức luồng hướng phân khúc, nhưng TCP với Sack là hướng byte thực. Tôi nghĩ rằng RFC không đặc biệt chi tiết về điều này.
sương mù

Cách ngăn xếp TCP quản lý bộ đệm gửi của nó, nó giống như những gì tôi đã viết trong câu hỏi cập nhật.
sương mù

@misteryes bài viết này phác thảo quá trình (với một số sơ đồ tuyệt vời, quá!).
Đột phá

Trong liên kết mà bạn đề xuất, có vẻ như tác giả vẫn thảo luận vấn đề theo cách hướng phân khúc, không phải theo cách hướng byte thực sự. Phải không?
sương mù

1
Tôi biết SACK trước khi tôi đăng câu hỏi này. Lúc đầu, tôi không nghĩ SACK có liên quan đến câu hỏi này. Theo tôi, nếu TCP không phải là định hướng byte mà là hướng theo phân khúc, thì SACK cũng sẽ giống như vậy. Sự khác biệt giữa SACK được kích hoạt và SACK bị vô hiệu hóa là với SACK, TCP cho phép một lỗ trình tự trong ack_seq. Nhưng tôi nghĩ lỗ trình tự tương ứng với một phân khúc. trong khi theo câu nói của bạn, lỗ hổng có thể là một nửa / một phần của một phân khúc.
sương mù

3

Kích thước phân đoạn có thể (và làm) thay đổi trong suốt thời gian kết nối. May mắn thay, TCP không cần phải ghi lại kích thước phân đoạn mà các gói riêng lẻ đã được gửi trước đó. Do đó, nó sẽ làm như sau:

  1. Bất cứ khi nào ACK đến, hãy đưa con trỏ đến byte chưa được xử lý đầu tiên tương ứng và loại bỏ bất kỳ bộ đệm không cần thiết nào.
  2. Khi có nhu cầu truyền lại (Truyền lại nhanh hoặc Hết giờ; KHÔNG ngay sau khi nhận được ACK đầu tiên!), Nó sẽ gửi lại trong kích thước phân đoạn hiện tại hợp lệ bắt đầu từ con trỏ đến byte chưa được xử lý đầu tiên.

Cả hai hoạt động được thực hiện độc lập với kích thước phân đoạn mà các byte ban đầu được gửi vào. Vì vậy, lý thuyết phải phù hợp với hầu hết các triển khai.

Hãy để tôi cung cấp một số nền tảng để giải thích:

TCP có sử dụng byte hoặc phân đoạn không? Đối với ứng dụng, TCP hiển thị giao diện luồng byte. Ngoài ra, tất cả các trường tiêu đề và biến nội bộ được tính bằng byte. Tuy nhiên, để truyền thông tin, TCP chia chúng thành các phân đoạn, vì việc gửi từng byte một sẽ khá lãng phí :-). Sử dụng bộ đếm byte ở mọi nơi có lợi thế là kích thước phân đoạn không cần duy trì không đổi trong suốt thời gian kết nối:

  • Các tùy chọn đang được giới thiệu, ví dụ: cõng SACK trên truyền lại (việc triển khai thực sự sẽ hiếm khi gặp phải điều này, nếu có)
  • Đường dẫn MTU thay đổi, ví dụ: một liên kết dọc theo đường dẫn thay đổi thành MTU thấp hơn hoặc liên kết MTU bị nghẽn cổ chai được đưa ra. Điều này xảy ra khi các đường hầm được thiết lập (VPN, PPPoE) hoặc giao thức định tuyến chọn một liên kết MTU khác. Điều này xảy ra trong IPv4 với bộ Do not Fragment (đúng với hầu hết các TCP hiện đại); luôn trong TCPv6).

BTW: SACK không phải là câu trả lời ở đây, vì người nhận sẽ (thường) chỉ sử dụng SACK nếu nó nhận ra một lỗ hổng trong luồng byte (nghĩa là, nếu một gói bị mất nhưng một gói sau đến).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.