Saya menjalankan program tertentu di linux yang terkadang macet. Jika Anda membukanya dengan cepat setelah itu, ia mendengarkan pada socket 49201 alih-alih 49200 seperti yang terjadi pertama kali. netstat mengungkapkan bahwa 49200 dalam keadaan TIME_WAIT.
Apakah ada program yang dapat Anda jalankan untuk segera memaksa soket keluar dari status TIME_WAIT?
TIME_WAIT
di server" , lewati saja tiga jawaban pertama yang menghindari pertanyaan alih-alih menjawabnya.Jawaban:
Biarkan saya uraikan. Transmission Control Protocol (TCP) dirancang untuk menjadi protokol transmisi data dua arah, terurut, dan andal antara dua titik akhir (program). Dalam konteks ini, istilah reliable artinya akan mentransmisikan kembali paket jika hilang di tengah. TCP menjamin keandalan dengan mengirimkan kembali paket Acknowledgement (ACK) untuk satu atau serangkaian paket yang diterima dari rekan.
Ini berlaku untuk sinyal kontrol seperti permintaan / respons penghentian. RFC 793 mendefinisikan status TIME-WAIT sebagai:
Lihat diagram keadaan TCP berikut:
TCP adalah protokol komunikasi dua arah, jadi ketika koneksi dibuat, tidak ada perbedaan antara klien dan server. Juga, salah satu dapat memanggil berhenti, dan kedua rekan perlu menyetujui untuk menutup untuk sepenuhnya menutup koneksi TCP yang ada.
Mari kita panggil yang pertama untuk memanggil berhenti sebagai yang lebih dekat aktif, dan rekan yang lain lebih dekat pasif. Ketika semakin dekat aktif mengirim FIN, negara pergi ke FIN-WAIT-1. Kemudian ia menerima ACK untuk FIN yang dikirim dan negara bagian pergi ke FIN-WAIT-2. Setelah menerima FIN juga dari pasif dekat, semakin dekat aktif mengirimkan ACK ke FIN dan negara pergi ke WAKTU-TUNGGU. Jika pasif dekat tidak menerima ACK ke FIN kedua, itu akan mentransmisikan kembali paket FIN.
RFC 793 menetapkan TIME-OUT menjadi dua kali Seumur Hidup Maksimum, atau 2MSL. Karena MSL, waktu maksimum sebuah paket dapat berkeliaran di Internet, diatur ke 2 menit, 2MSL adalah 4 menit. Karena tidak ada ACK ke ACK, semakin dekat aktif tidak dapat melakukan apa pun kecuali menunggu 4 menit jika mematuhi protokol TCP / IP dengan benar, kalau-kalau pengirim pasif belum menerima ACK ke FIN (secara teoritis) .
Pada kenyataannya, paket yang hilang mungkin langka, dan sangat langka jika semuanya terjadi di dalam LAN atau dalam satu mesin.
Untuk menjawab pertanyaan dengan kata demi kata, Bagaimana cara menutup paksa soket di TIME_WAIT ?, saya masih akan tetap menggunakan jawaban asli saya:
Secara praktis, saya akan memprogramnya sehingga mengabaikan status TIME-WAIT menggunakan opsi SO_REUSEADDR seperti yang disebutkan WMR. Apa sebenarnya yang dilakukan SO_REUSEADDR?
sumber
/etc/init.d/networking
adalah platform-spesifik (Debian?) Sehingga baris perintah yang tepat akan berbeda (kadang-kadang agak radikal) untuk sistem lain. Saya setuju dengan komentator lain bahwa ini seperti kerja keras yang berlebihan dan jelas mengganggu layanan jaringan yang tidak terkait.Saya tidak tahu apakah Anda memiliki kode sumber dari program tertentu yang sedang Anda jalankan, tetapi jika demikian Anda bisa mengatur SO_REUSEADDR via
setsockopt(2)
yang memungkinkan Anda untuk mengikat pada alamat lokal yang sama bahkan jika soketnya dalam keadaan TIME_WAIT (kecuali jika itu soket sedang mendengarkan secara aktif, lihatsocket(7)
).Untuk informasi lebih lanjut tentang keadaan TIME_WAIT lihat FAQ soket Unix .
sumber
SO_REUSEADDR
tidak "menutup" soket. Ini hanya memungkinkan Anda untuk menggunakan kembali yang sudah dibuka. Jadi pertanyaannya masih, "Bagaimana cara menutup soket secara paksaTIME_WAIT
?"SO_REUSEADDR
akan membiarkanbind()
melanjutkan; tetapi jika Anda ingin mendengarkan soket itu,listen()
akan mengembalikanEADDRINUSE
semua sama. Dengan kata lain, jawaban ini dapat membantu perangkat lunak klien menggunakan porta sesaat, tetapi tidak memecahkan masalah untuk perangkat lunak server.Sejauh yang saya tahu tidak ada cara untuk secara paksa menutup soket di luar penulisan pengontrol sinyal yang lebih baik ke dalam program Anda, tetapi ada file / proc yang mengontrol berapa lama waktu tunggu habis. File tersebut adalah
dan Anda dapat mengatur batas waktu ke 1 detik dengan melakukan ini:
Namun, halaman ini berisi peringatan tentang kemungkinan masalah keandalan saat mengatur variabel ini.
Ada juga file terkait
yang mengontrol apakah soket TIME_WAIT dapat digunakan kembali (mungkin tanpa batas waktu).
Secara kebetulan, dokumentasi kernel memperingatkan Anda untuk tidak mengubah salah satu dari nilai-nilai ini tanpa 'saran / permintaan ahli teknis'. Bukan aku.
Program harus ditulis untuk mencoba mengikat ke port 49200 dan kemudian bertambah 1 jika port sudah digunakan. Oleh karena itu, jika Anda memiliki kontrol kode sumber, Anda dapat mengubah perilaku ini untuk menunggu beberapa detik dan coba lagi di port yang sama, alih-alih bertambah.
sumber
1
berfungsi untuk koneksi di masa mendatang, tetapi bagaimana dengan koneksi saat ini yang sudah dibuka?Sebenarnya ada cara untuk mematikan koneksi - killcx . Mereka mengklaim itu berfungsi dalam kondisi koneksi apa pun (yang belum saya verifikasi). Anda perlu mengetahui antarmuka di mana komunikasi terjadi, tampaknya menganggap eth0 secara default.
UPDATE: solusi lain adalah cutter yang datang dalam beberapa repositori distro linux.
sumber
Opsi lain adalah menggunakan opsi SO_LINGER dengan batas waktu 0. Dengan cara ini, ketika Anda menutup soket ditutup secara paksa, mengirim RST alih-alih masuk ke perilaku penutupan FIN / ACK. Ini akan menghindari status TIME_WAIT, dan mungkin lebih sesuai untuk beberapa penggunaan.
sumber
Solusi alternatif adalah dengan memiliki beberapa proxy yang andal atau perangkat lunak penerusan port yang mendengarkan pada port 49200, kemudian meneruskan koneksi ke salah satu dari beberapa contoh program Anda yang kurang dapat diandalkan menggunakan port yang berbeda ... HAPROXY muncul dalam pikiran.
Kebetulan port yang Anda hubungkan cukup tinggi. Anda bisa mencoba menggunakan yang tidak terpakai tepat di atas rentang 0-1024. Sistem Anda cenderung menggunakan nomor port yang lebih rendah sebagai porta sesaat.
sumber
TIME_WAIT adalah masalah paling umum dalam arsitektur server klien pemrograman soket. Tunggu beberapa detik mencoba secara berkala adalah solusi terbaik untuk itu. Untuk aplikasi waktu nyata yang mereka perlukan server harus segera bangun. Ada opsi SO_REUSEADDR untuk mereka.
sumber