socket.shutdown vs socket.close


122

Geçenlerde buna benzer bir kod gördüm (tabii ki çorap bir soket nesnesi):

sock.shutdown(socket.SHUT_RDWR)
sock.close()

Sokette kapatmayı çağırıp sonra kapatmanın tam olarak amacı nedir? Bir fark yaratırsa, bu soket engellemesiz IO için kullanılıyor.

Yanıtlar:


38

İşte bir açıklama :

Bir soket artık gerekli olmadığında, çağıran program soket tanımlayıcısına yakın bir alt yordam uygulayarak soketi atabilir. Güvenilir bir teslimat soketinde, kapanma gerçekleştiğinde kendisiyle ilişkilendirilmiş veriler varsa, sistem veri aktarımını denemeye devam eder. Bununla birlikte, veriler hala teslim edilmezse, sistem verileri atar. Uygulama programının bekleyen herhangi bir veriyi kullanmaması durumunda, kapatmadan önce soketteki kapatma alt yordamını kullanabilir.


241

Arama closeve shutdowntemel soket üzerinde iki farklı etkiye sahiptir.

Dikkat edilmesi gereken ilk şey, soketin temeldeki işletim sisteminde bir kaynak olduğu ve birden çok işlemin aynı temel soket için bir tutamaca sahip olabileceğidir.

Onu çağırdığınızda closetutamaç sayısını bir azaltır ve tutamaç sayısı sıfıra ulaşırsa, soket ve ilgili bağlantı normal kapatma prosedüründen geçer (eşe etkin bir şekilde FIN / EOF gönderir) ve soket serbest bırakılır.

Burada dikkat edilmesi gereken nokta, başka bir işlemin sokete hala bir tutamacı olduğu için tutamaç sayısı sıfıra ulaşmazsa, bağlantı kapatılmaz ve yuvanın ayrılmamasıdır.

Öte yandan shutdown, okuma ve yazma çağrısı , temeldeki bağlantıyı kapatır ve sokete kaç işlemin tanıtıcısı olduğuna bakılmaksızın eşe bir FIN / EOF gönderir. Ancak, soketi serbest bırakmaz ve daha sonra yine de close çağırmanız gerekir.


harika cevap, ne shutdown()
Matt Joiner

2
Okuma için bir shutdown () bir FIN paketi göndermesine neden olabilir mi? yani kapatma (sock_fd, 1);
ernesto

Her zaman bir .shutdown()sonraki hatta aramak akıllıca olur .close()mu? Yoksa arada bir gecikme mi olmalı?
Luc

@Luc Tamamen ne yaptığınıza bağlıdır.
Robert S. Barnes

2
@Luc O zaman diğer işlemlerin soket için bir tutacağı olmadığı sürece sadece kapat sorun değil.
Robert S. Barnes

17

Kapatma ve kapatma açıklaması: Sorunsuz kapatma (msdn)

Kapatma (sizin durumunuzda), bağlantının diğer ucuna soketten okuma veya soketten yazma gibi başka bir niyet olmadığını gösterir. Ardından, kapat, soketle ilişkili tüm belleği boşaltır.

Kapatmayı atlamak, bağlantı düzgün bir şekilde kapatılana kadar soketin işletim sistemi yığınında kalmasına neden olabilir.

IMO, 'kapatma' ve 'kapat' isimleri yanıltıcıdır, 'kapat' ve 'yok et' farklılıkları vurgular.


Diğer uca, okumaya yönelik başka bir niyet olmadığını göstermez. Okuma için kapatma, eşe hiçbir şey göndermez.
Marquis of Lorne

7

Soket Programlama NASIL belgesinde ( py2 / py3 ) doğrudan bahsedilmektedir

bağlantısının kesilmesi

Açıkçası, sizden shutdownönce bir soket kullanmalısınız close. shutdownDiğer ucunda sokete bir danışma olduğunu. Bunu ilettiğiniz argümana bağlı olarak, " Artık göndermeyeceğim, ancak yine de dinleyeceğim " veya " Dinlemiyorum, iyi kurtulduk! ”. Bununla birlikte, çoğu soket kitaplığı, normalde a closeile aynı olan bu görgü kuralını kullanmayı ihmal eden programcılara çok kullanılır shutdown(); close(). Bu nedenle çoğu durumda, açık bir kapatmaya gerek yoktur.

...


Bu bilgi doğru değil. Yalnızca (1) işlemi çatalladıysanız ve kesinlikle FIN'i şimdi göndermek istiyorsanız veya (2) her iki eşin de birbirine yakın olacağı şekilde karşılıklı bir EOS'a okuma protokolüne giriyorsanız, yazma için bir soketin kapatılması gerekir. aynı zamanda. Aksi takdirde close()yeterlidir. Python belgeleri düzeltilmelidir.
Marquis of Lorne

4

Yukarıdaki kod yanlış değil mi?

Kapatma çağrısından hemen sonra yapılan kapatma çağrısı, çekirdeğin tüm giden arabellekleri yine de atmasına neden olabilir.

Http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable'a göre, birinin kapanma ile kapanma arasında beklemesi gerekir. okuma 0 döndürene kadar kapatın.


Doğru değil. Çekirdek, yalnızca bağlantı sıfırlandıysa giden arabellekleri atacaktır; bu, yerel uygulama zaten gelen tüm bekleyen gelen verileri okumamışsa veya eş SO_LINGER ile karıştırmışsa, ki bunu yapmaması gerekir. . Kapanmadan önce uyumaya veya kapatmayı çağırmaya bile gerek yoktur. Bu konuyla ilgili pek çok yanlış bilgi var.
Marquis of Lorne


1

Kapatma (1), soket no'yu daha fazla veri göndermeye zorlar

Bu yararlıdır

1- Tampon yıkama

2- Garip hata tespiti

3- Güvenli koruma

Daha fazla açıklayayım, A'dan B'ye bir veri gönderdiğinizde, B'ye gönderilmesi garanti edilmez, yalnızca A os arabelleğine gönderilmesi garanti edilir, bu da onu B os arabelleğine gönderir

Dolayısıyla, A'da shutdown (1) 'i çağırarak, A'nın arabelleğini temizlersiniz ve tampon boş değilse bir hata oluşur, yani: veri henüz eşe gönderilmemiştir.

Ancak bu geri alınamazsa, tüm verilerinizi tamamen gönderdikten sonra bunu yapabilirsiniz ve en azından eş işletim sistemi arabelleğinde olduğundan emin olmak istersiniz.


Kapatma, yıkamayı zorlamaz. Tamponlama durumu değişmedi. Ve eğer tampon boş değilse, herhangi bir hata oluşmaz. FIN yalnızca bekleyen verilerin arkasında sıralanır. Cevap tamamen yanlış.
Marquis of Lorne
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.