Di Linux (server langsung saya ada di RHEL 5.5 - tautan LXR di bawah ini ke versi kernel di dalamnya), man 7 ip
mengatakan:
Alamat soket lokal TCP yang telah diikat tidak tersedia untuk beberapa waktu setelah ditutup, kecuali jika flag SO_REUSEADDR telah ditetapkan.
Saya tidak menggunakan SO_REUSEADDR
. Berapa lama "beberapa waktu"? Bagaimana saya bisa mengetahui berapa lama, dan bagaimana saya bisa mengubahnya?
Saya sudah mencari-cari di sekitar ini, dan telah menemukan beberapa informasi, tidak ada yang benar-benar menjelaskan hal ini dari perspektif pemrogram aplikasi. Yakni:
- TCP_TIMEWAIT_LEN di
net/tcp.h
adalah "berapa lama menunggu untuk menghancurkan status TIME-WAIT", dan diperbaiki pada "sekitar 60 detik" - / proc / sys / net / ipv4 / tcp_fin_timeout adalah "Saatnya memegang soket dalam keadaan FIN-WAIT-2, jika ditutup oleh pihak kami", dan "Nilai default adalah 60sec"
Di mana saya tersandung adalah dalam menjembatani kesenjangan antara model kernel dari siklus hidup TCP, dan model pemrogram port tidak tersedia, yaitu, dalam memahami bagaimana keadaan ini berhubungan dengan "beberapa waktu".
man 2 bind
jika Anda tidak percaya padaku. Memang, itu mungkin bukan hal pertama yang orang pikirkan ketika seseorang mengatakan "bind", cukup adil.bind
, tetapi tag di sini secara khusus diterapkan ke server DNS. Kami tidak memiliki tag untuk setiap panggilan sistem yang mungkin.Jawaban:
Saya percaya bahwa ide soket tidak tersedia untuk suatu program adalah untuk memungkinkan segmen data TCP yang masih dalam perjalanan untuk tiba, dan dibuang oleh kernel. Yaitu, mungkin saja suatu aplikasi memanggil
close(2)
soket, tetapi merutekan keterlambatan atau kecelakaan untuk mengontrol paket atau apa saja yang Anda bisa izinkan sisi lain koneksi TCP mengirim data untuk sementara waktu. Aplikasi telah mengindikasikan bahwa ia tidak lagi ingin berurusan dengan segmen data TCP, jadi kernel harus membuangnya begitu mereka masuk.Saya meretas sedikit program di C yang dapat Anda kompilasi dan gunakan untuk melihat berapa lama waktu tunggu:
Saya mencoba program ini pada 3 mesin yang berbeda, dan saya mendapatkan waktu variabel, antara 55 dan 59 detik, ketika kernel menolak untuk mengizinkan pengguna non-root untuk membuka kembali soket. Saya mengkompilasi kode di atas ke executable bernama "pembuka", dan menjalankannya seperti ini:
Saya membuka jendela lain dan melakukan ini:
Itu menyebabkan instance pertama dari "pembuka" menerima koneksi, lalu menutupnya. Contoh kedua dari "pembuka" mencoba untuk
bind(2)
ke port TCP 7896 setiap detik. "pembuka" melaporkan penundaan 55 hingga 59 detik.Googling sekitar, saya menemukan bahwa orang merekomendasikan melakukan ini:
untuk mengurangi interval itu. Itu tidak berhasil untuk saya. Dari 4 mesin linux yang saya akses, dua memiliki 30 dan dua memiliki 60. Saya juga menetapkan nilai serendah 10. Tidak ada perbedaan dengan program "pembuka".
Melakukan ini:
memang mengubah hal-hal. "Pembuka" kedua hanya membutuhkan waktu sekitar 3 detik untuk mendapatkan soket baru.
sumber