Bagaimana cara kerja `TIME_WAIT` di sisi server?

11

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:

  1. Sisi server TIME_WAITtidak berbahaya
  2. 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_WAITpada klien dapat menjadi masalah - klien dapat kehabisan port yang tersedia, jadi pada dasarnya hal di atas merekomendasikan untuk memindahkan beban TIME_WAITke sisi klien di mana itu bisa menjadi masalah, dari sisi server di mana itu bukan masalah.

Sisi klien TIME_WAITtentu 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_LINGERdengan 0 timeout, atau campur tangan dengan tcp_tw sysctls) memerangi sisi klien TIME_WAITdengan 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_WAITsangat membantu. Alasannya TIME_WAITbahkan ada di sana, adalah karena itu mencegah menyuntikkan TCPfragmen basi ke aliran mereka tidak lagi milik. Untuk sisi klien, TIME_WAITitu dicapai hanya dengan membuatnya tidak mungkin untuk membuat koneksi dengan ip:portpasangan 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_WAITbenar - benar tidak melakukan apa-apa, dan dibiarkan begitu saja karena RFCmengharuskannya?
  • Apakah alasan rekomendasi tersebut bagi klien untuk memulai close () karena server TIME_WAITtidak berguna?
Pawel Veselov
sumber
Anda tidak akan kehabisan port kecuali Anda hanya memiliki 1 klien. Anda memiliki 65535 port untuk setiap kombinasi IP klien / server. Koneksi dari 1.2.3.4:1111 berbeda dari 4.3.2.1:1111. Hanya butuh beberapa byte memori untuk setiap koneksi TIME_WAIT.
Marki555

Jawaban:

1

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

        When a connection is closed actively, it MUST linger in
        TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
        However, it MAY accept a new SYN from the remote TCP to
        reopen the connection directly from TIME-WAIT state, if it:

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.

Marko Kohtala
sumber
0

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.

Khushil
sumber
Masih tidak menjelaskan apa yang terjadi ketika koneksi server klien> dimulai, dan server memiliki pasangan yang terkunci di TIME_WAIT
Pawel Veselov
Silakan lihat stackoverflow.com/questions/1490196/… - Jawaban ada apa yang Anda cari.
Khushil
0

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.

basos
sumber
Tolong jelaskan; ketika Anda bertanya apakah sisi-server TW melakukan sesuatu, Anda bertanya-tanya apakah koneksi yang sama dapat digunakan kembali selama periode TW. Jawabannya adalah tidak karena koneksi, seperti yang didefinisikan oleh tupple, terjadi di tabel tcp server. Jika klien mencoba untuk segera membuka koneksi yang sama, ia akan menerima RST, yang secara efektif menolak koneksi tcp. Omong-omong, artikel dari Khushil sangat deskriptif.
basos
Saya sangat menyesal, jawaban Anda sebenarnya menjawab pertanyaan, saya salah baca, dan telah menarik komentar saya. Namun, sepertinya juga tidak benar, karena saya memiliki kode yang sepertinya membuktikan bahwa tidak ada perlindungan dari sisi server TIME_WAIT(saya memperbarui pertanyaan dengan info itu). Referensi @ Khushil tidak mencakup TIME_WAITkasus sisi server dengan cukup detail.
Pawel Veselov
-2

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.

jrrk
sumber
Saya sangat menyesal, tetapi ini tidak menjawab pertanyaan saya.
Pawel Veselov