jika suatu paket TCP mendapat pengakuan sebagian, bagaimana mekanisme pengiriman ulang akan bereaksi?

12

jika klien tcp mengirim paket, dengan nomor urut 10.000 hingga 20.000, ke server tcp. tcp akan merespons dengan ACK dengan seq_ack 20001.

jika saya mencegat paket TCP dari klien, dan membagi paket menjadi 2 segmen tcp, satu dengan seq dari 10.000 hingga 15.000, dan yang lainnya dengan seq dari 15001 hingga 20000. Dan kemudian 2 segmen TCP ini dikirim ke server TCP. Asumsikan bahwa segmen kedua hilang di jalur. Server TCP akan merespons ACK dengan seq_ack 15001.

Sekarang karena klien TCP mengirim paket integral dengan seq 10000 hingga 20000, tetapi mendapat ACK dengan 15001, dari sudut pandang klien, ini aneh. Bagaimana ini akan bereaksi? Secara teori, klien harus mengirim ulang byte dari seq 15001 ke 20000, yaitu, klien akan mengirimkan paket baru dari seq 15001. Tetapi bagaimana dengan praktiknya, dalam implementasi TCP stack, apakah sama seperti dalam teori?

Saya pikir dalam buffer pengiriman TCP, ketika segmen tcp dikirim, segmen itu tetap di sana sampai ACK. Ketika ACK datang, byte ini untuk segmen dihapus dari buffer. Ada pointer di buffer kirim, ketika ACK datang, pointer menunjuk ke lokasi di mana ack_seq sesuai. Bytes yang berada di bawah ack_seq dihapus. Dengan cara ini, seluruh segmen tidak perlu dikirim ulang?

Misteri
sumber

Jawaban:

8

Ini disebut pengakuan selektif , dan sudah termasuk dalam spesifikasi TCP yang ditentukan dalam RFC 2018 . Ini akan memungkinkan klien untuk mengirim ulang hanya byte 15001 ke 20000 (karena mereka berada dalam paket / segmen yang berbeda jika Anda telah membaginya seperti yang Anda katakan), tetapi yang lebih menarik, itu bahkan memungkinkan ucapan terima kasih yang rusak.

Dari RFC 2018:

Saat menerima ACK yang berisi opsi SACK, pengirim data HARUS merekam pengakuan selektif untuk referensi di masa mendatang. Pengirim data diasumsikan memiliki antrian pengiriman ulang yang berisi segmen yang telah dikirim tetapi belum diakui, dalam urutan nomor urut.

Mendukung SACKyang tidak diperlukan oleh spesifikasi TCP. Jika salah satu klien atau server tidak mendukung pengakuan selektif, memang semua byte 10.000 hingga 20.000 harus ditransmisikan kembali.

Dalam implementasi TCP stack, apakah sama dengan teori?

Biasanya SACK ini didukung, seperti kinerja, efisiensi, dan keuntungan latency yang signifikan - terutama dalam jaringan seperti internet.

Namun bagaimanapun, asumsi-asumsi ini harus berlaku bahkan jika Anda secara manual memanipulasi paket-paket seperti yang Anda nyatakan. Sebagai per RFC 793 , minimal, seluruh jendela data harus ditransmisikan ulang, tapi penerima tidak tahu bahwa data diterima setidaknya berlaku . Untuk detail implementasi, Bagian 3.3 - Nomor Urutan dari RFC 793.

Untuk garis besar seluruh proses baik dengan dan tanpa dukungan pengakuan selektif, lihat artikel ini (yang mencakup beberapa diagram yang sangat berguna).

Penerobosan
sumber
itu agak aneh bagi saya, karena TCP berbasis aliran, protokol byte-oriented. Mengapa harus mentransmisikan ulang seluruh segmen? Sepertinya saya bahwa TCP tanpa SAKC adalah protokol aliran berorientasi segmen, tetapi TCP dengan Sack adalah byte nyata yang berorientasi. Saya pikir RFC tidak secara khusus menguraikan hal ini.
Misteri
bagaimana TCP stack mengelola buffernya, apakah sama dengan apa yang saya tulis dalam pertanyaan yang diperbarui.
Misteri
@misteryes artikel ini menguraikan prosesnya (dengan beberapa diagram hebat juga!).
Terobosan
Di tautan yang Anda rekomendasikan, tampaknya penulis masih membahas masalah dengan cara yang berorientasi segmen, bukan dengan cara yang benar-benar berorientasi byte. Bukan?
Misteri
1
Saya tahu SACK sebelum mengirim pertanyaan ini. Pada awalnya saya tidak berpikir SACK ada hubungannya dengan pertanyaan ini. Menurut pendapat saya, jika TCP tidak berorientasi byte tetapi berorientasi segmen, maka SACK juga harus sama. Perbedaan antara SACK-enabled dan SACK-disable adalah dengan SACK, TCP memungkinkan lubang urutan di ack_seq. Tapi saya pikir lubang urutan sesuai dengan segmen. sedangkan menurut pepatah Anda, lubang bisa setengah / bagian dari segmen.
Misteri
3

Ukuran segmen dapat (dan memang) berubah sepanjang masa koneksi. Untungnya, TCP tidak perlu merekam ukuran segmen yang dikirim paket individu sebelumnya. Karena itu, ia akan melakukan hal berikut:

  1. Setiap kali ACK tiba, naikkan pointer ke byte pertama yang tidak diakui sesuai dengan itu dan buang buffer yang sekarang tidak dibutuhkan.
  2. Ketika diperlukan untuk pengiriman ulang (Fast Retransmit atau Timeout; BUKAN segera setelah penerimaan ACK pertama!), Itu akan dikirim dalam ukuran segmen yang berlaku saat ini mulai dari pointer ke byte pertama yang tidak diakui.

Kedua operasi dilakukan secara independen dari ukuran segmen byte ini pada awalnya dikirim. Jadi teori harus cocok dengan sebagian besar implementasi.

Biarkan saya memberikan latar belakang untuk menjelaskan:

Apakah TCP menggunakan byte atau segmen? Untuk aplikasi, TCP memperlihatkan antarmuka aliran byte. Juga, semua bidang header dan variabel internal dalam byte. Namun, untuk mengirimkan informasi, TCP memotong mereka dalam segmen-segmen, karena mengirim byte satu-per-satu akan sangat boros :-). Menggunakan penghitung byte di mana saja memiliki keuntungan bahwa ukuran segmen tidak perlu tetap konstan selama masa koneksi:

  • Opsi sedang diperkenalkan, misalnya membonceng SACK pada pengiriman ulang (implementasi nyata jarang akan menghadapi ini, jika sama sekali)
  • Path MTU berubah, misalnya satu tautan di sepanjang path berubah ke MTU yang lebih rendah atau tautan MTU bottleneck dinaikkan. Ini terjadi ketika terowongan dibuat (VPN, PPPoE) atau protokol perutean memilih tautan MTU yang berbeda. Ini terjadi di IPv4 dengan set Don't Fragment (berlaku untuk sebagian besar TCP modern); selalu dalam TCPv6).

BTW: SACK bukan jawabannya di sini, karena penerima akan (biasanya) hanya menggunakan SACK jika ia mengenali lubang dalam aliran byte (yaitu, jika suatu paket hilang tetapi paket berikut tiba).

Marcel Waldvogel
sumber