Bu konuda birkaç SE sorusu olduğunu biliyorum ve bu noktaya gelmeden önce önemli olanların çoğunu okuduğuma inanıyorum.
"Sunucu tarafı TIME_WAIT
" ile, sunucu tarafında close () başlatılan sunucu tarafı soket çiftinin durumunu kastediyorum.
Sık sık bana aykırı gelen bu ifadeleri görüyorum:
- Sunucu tarafı
TIME_WAIT
zararsızdır - Ağ uygulamalarınızı, istemcilerin yakın başlatması için tasarlamanız gerekir (), bu nedenle
TIME_WAIT
Bu çelişkili bulmamın nedeni TIME_WAIT
, istemcide bir sorun olabileceğidir - istemci kullanılabilir bağlantı noktalarından kaçabilir, bu nedenle özünde yukarıdaki, yükün TIME_WAIT
sorun olabileceği istemci tarafına taşınmasını tavsiye eder . sorun olmayan sunucu tarafı.
İstemci tarafı TIME_WAIT
elbette sadece sınırlı sayıda kullanım durumu için bir sorundur. İstemci-sunucu çözümlerinin çoğu bir sunucuyu ve birçok istemciyi içerir, istemciler genellikle bir sorun olması için yeterince yüksek sayıda bağlantıyla uğraşmazlar ve öyle olsalar bile, "akılcı" için bir takım öneriler vardır ( aksine SO_LINGER
0 zaman aşımı ile, ya da) tcp_tw sysctl ile mücadele istemci tarafı karışma TIME_WAIT
çok hızlı bir şekilde çok fazla sayıda bağlantı oluşturmak kaçınarak. Ancak bu her zaman mümkün değildir, örneğin:
- izleme sistemleri
- yük jeneratörleri
- vekiller
Diğer taraftan, sunucu tarafının nasıl yardımcı olduğunu bile anlamıyorum TIME_WAIT
. Bunun nedeni TIME_WAIT
bile orada, TCP
artık ait olmadıkları akışlara eski parçaların enjekte edilmesini engellemesidir . İstemci tarafı TIME_WAIT
için ip:port
, bu eski bağlantının sahip olabileceği aynı çiftlerle bir bağlantı oluşturmayı imkansız hale getirerek gerçekleştirilir (kullanılan çiftler tarafından kilitlenir TIME_WAIT
). Ancak sunucu tarafı için, yerel adres kabul edilen bağlantı noktasına sahip olacağından ve her zaman aynı olacağından ve sunucu (AFAIK, sadece ampirik kanıtım var) bağlantıyı reddedeceği için bu önlenemez çünkü gelen eş, yuva tablosunda zaten var olan adres çiftini oluşturur.
Sunucu tarafı TIME-WAIT'ın yok sayıldığını gösteren bir program yazdım. Ayrıca, test 127.0.0.1'de yapıldığı için, çekirdeğin, sunucu tarafı mı yoksa istemci tarafı mı olduğunu bile belirten özel bir biti olmalıdır (aksi takdirde demet aynı olacaktır).
Kaynak: http://pastebin.com/5PWjkjEf , Fedora 22'de test edildi, varsayılan net yapılandırma.
$ 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
Bu nedenle, sunucu tarafı için TIME_WAIT
, aynı bağlantı noktası çiftindeki bağlantılar hemen ve başarıyla yeniden kurulabilir ve istemci tarafı TIME-WAIT
için ikinci yinelemede connect()
haklı olarak başarısız olabilir
Özetlemek gerekirse, soru iki katlıdır:
- Sunucu tarafı
TIME_WAIT
gerçekten hiçbir şey yapmıyor mu ve bu şekilde bırakılıyorRFC
mu? - Öneri, sunucunun
TIME_WAIT
yararsız olduğu için istemcinin close () başlatması mıdır?
TIME_WAIT
.