Saya tahu ada beberapa pertanyaan SE tentang ini, dan saya percaya saya membaca banyak dari mereka yang penting sebelum sampai ke titik ini.
Yang dimaksud dengan "sisi server TIME_WAIT
" yang saya maksud adalah keadaan pasangan soket sisi server yang memulai () di sisi server.
Saya sering melihat pernyataan-pernyataan ini yang kedengarannya bertentangan dengan saya:
- Sisi server
TIME_WAIT
tidak berbahaya - Anda harus merancang aplikasi jaringan Anda agar klien memulai close (), oleh karena itu klien harus
TIME_WAIT
Alasan saya menemukan kontradiksi ini adalah karena TIME_WAIT
pada klien dapat menjadi masalah - klien dapat kehabisan port yang tersedia, jadi pada dasarnya hal di atas merekomendasikan untuk memindahkan beban TIME_WAIT
ke sisi klien di mana itu bisa menjadi masalah, dari sisi server di mana itu bukan masalah.
Sisi klien TIME_WAIT
tentu saja hanya masalah untuk jumlah kasus penggunaan yang terbatas. Sebagian besar solusi client-server akan melibatkan satu server dan banyak klien, klien biasanya tidak berurusan dengan volume koneksi yang cukup tinggi untuk itu menjadi masalah, dan bahkan jika mereka melakukannya, ada sejumlah rekomendasi untuk "sehat" ( sebagai lawan SO_LINGER
dengan 0 timeout, atau campur tangan dengan tcp_tw sysctls) memerangi sisi klien TIME_WAIT
dengan menghindari membuat terlalu banyak koneksi terlalu cepat. Tapi itu tidak selalu layak, misalnya untuk kelas aplikasi seperti:
- sistem pemantauan
- memuat generator
- proksi
Di sisi lain, saya bahkan tidak mengerti bagaimana sisi server TIME_WAIT
sangat membantu. Alasannya TIME_WAIT
bahkan ada di sana, adalah karena itu mencegah menyuntikkan TCP
fragmen basi ke aliran mereka tidak lagi milik. Untuk sisi klien, TIME_WAIT
itu dicapai hanya dengan membuatnya tidak mungkin untuk membuat koneksi dengan ip:port
pasangan yang sama dengan yang dimiliki oleh koneksi basi ini (pasangan yang digunakan dikunci oleh TIME_WAIT
). Tetapi untuk sisi server, ini tidak dapat dicegah karena alamat lokal akan memiliki port penerima, dan selalu akan sama, dan server tidak bisa (AFAIK, saya hanya punya bukti empiris) menolak koneksi hanya karena rekan yang masuk akan membuat pasangan alamat yang sama yang sudah ada dalam tabel socket.
Saya memang menulis sebuah program yang menunjukkan bahwa TIME-WAIT sisi-server diabaikan. Selain itu, karena pengujian dilakukan pada 127.0.0.1, kernel harus memiliki bit khusus yang bahkan memberitahukannya apakah itu sisi server atau sisi klien (karena jika tidak tupel akan sama).
Sumber: http://pastebin.com/5PWjkjEf , diuji pada Fedora 22, konfigurasi net default.
$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp TIME-WAIT 0 0 127.0.0.1:44400 127.0.0.1:44401
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address
Jadi, untuk sisi server TIME_WAIT
, koneksi pada pasangan port yang persis sama dapat dibangun kembali dengan segera dan berhasil, dan untuk sisi klien TIME-WAIT
, pada iterasi kedua connect()
gagal dengan benar
Untuk meringkas, pertanyaannya adalah dua kali lipat:
- Apakah sisi server
TIME_WAIT
benar - benar tidak melakukan apa-apa, dan dibiarkan begitu saja karenaRFC
mengharuskannya? - Apakah alasan rekomendasi tersebut bagi klien untuk memulai close () karena server
TIME_WAIT
tidak berguna?
TIME_WAIT
.Jawaban:
Di sisi server istilah TCP di sini berarti host yang memiliki soket dalam keadaan DENGARKAN.
RFC1122 memungkinkan soket dalam keadaan TIME-WAIT untuk menerima koneksi baru dengan beberapa kondisi
Untuk rincian yang tepat pada kondisi, silakan lihat RFC1122 . Saya berharap juga harus ada OPEN pasif yang cocok pada soket (soket dalam status LISTEN).
OPEN aktif (panggilan sisi klien terhubung) tidak memiliki pengecualian seperti itu dan harus memberikan kesalahan ketika soket dalam WAKTU-TUNGGU, sesuai RFC793 .
Dugaan saya untuk rekomendasi pada klien (dalam istilah TCP host melakukan OPEN aktif yaitu terhubung) dimulai dekat sama seperti milik Anda, bahwa dalam kasus umum menyebar soket WAKTU-TUNGGU pada host lebih banyak di mana ada banyak sumber daya untuk soket. Dalam kasus umum, klien tidak mengirim SYN yang akan menggunakan kembali soket TIME-WAIT di server. Saya setuju bahwa untuk menerapkan rekomendasi tersebut masih tergantung pada use case.
sumber
Ini mungkin adalah contoh paling jelas dari apa yang sebenarnya dilakukan TIME-WAIT dan yang lebih penting mengapa itu penting. Ini juga menjelaskan mengapa untuk menghindari beberapa tips 'ahli' pada mesin Linux untuk 'mengurangi' WAKTU-SEDANG.
sumber
Sesi tcp diidentifikasi oleh tupple (sourceIP, sourcePort, destIP, destPort). Karenanya TIME_WAIT berfungsi pada setiap koneksi tcp.
Mengenai sisi penutupan, dalam beberapa skenario, penutupan dari sisi klien dapat mengurangi soket TIME_WAIT di server, sehingga sedikit mengurangi memori. Dalam kasus ketika ruang soket dapat habis (karena penipisan porta sesaat) (misalnya klien serakah dengan banyak koneksi ke server yang sama), masalah ini harus diselesaikan di sisi mana pun.
sumber
TIME_WAIT
(saya memperbarui pertanyaan dengan info itu). Referensi @ Khushil tidak mencakupTIME_WAIT
kasus sisi server dengan cukup detail.Anda tidak pernah dapat yakin dengan protokol yang tidak dapat diandalkan, bahwa Anda telah menerima pesan terakhir dari perangkat rekan Anda, oleh karena itu berbahaya untuk menganggap bahwa rekan Anda telah menutup telepon agak tiba-tiba. Ini adalah kelemahan utama dari protokol TCP yang hanya 65.000 atau lebih port dapat dibuka secara bersamaan. Tetapi cara untuk mengatasinya adalah dengan pindah ke server farm, yang timbangannya lebih baik dengan beban, daripada dengan mendaur ulang nomor port dengan cepat. Pada akhir klien, sangat tidak mungkin bahwa Anda akan kehabisan port jika itu adalah workstation dasar.
sumber