2016-03-21 19 views
0

Gelen bağlantıları kabul eden ve bağlantı başına bir bağlantı kullanarak verileri geri gönderen gevent kullanılarak yazılmış küçük bir HTTP sunucum var. (Yerel) istemcisi sunucu tarafı istemciye yazar öldüğünde soket CLOSE_WAIT durumda olmasına rağmen başarılı: Artıkgevent tcp soketi bağlantısı kesildi ancak veri gönderebilir

$ ls -l /proc/21860/fd |grep 22 
lrwx------. 1 mathieu mathieu 64 Mar 21 19:55 22 -> socket:[187093] 
$ lsof |grep 187093 
python 21860  mathieu 22u  IPv4    187093  0t0  TCP localhost.localdomain:36072->localhost.localdomain:48908 (CLOSE_WAIT) 

, ben gevent.socket.socket ile oluşturulan soketin gönderme yöntemini beklenebilir bir istisna ile başarısız olmak ama hiçbiri yok!

def send(socket, data): 
    sent = socket.send(data) 
    while sent != len(data): 
     data = data[sent:] 
     sent = socket.send(data) 

Beklentim yanlış mı? Eğer değilse, burada yanlış ne olabilir?

cevap

0

Biraz hata ayıkladıktan sonra, soket API'sinin TCP'nin üstünde nasıl davrandığına dair beklentim yanlış çıktı. Potansiyel okuyucuların götürmek için dikkatle TCP option SO_LINGER (zero) - when it's required

şeyler okumak isteyebilirsiniz:()

  1. istemci tarafında yakın kabaca "Ben, verileri size bıktım" anlamına sunucuya FIN gönderir. Bu, sunucunun yine de verileri geri gönderebileceği anlamına gelir.
  2. İstemci kapatıldıktan sonra sunucu bir yazma girişiminde bulunursa, yazma işlemi başarılı olacaktır (kullanıcı alanından kernelspace'e kopyalanan bayt sayısını döndürür), veri istemciye gönderilir, istemci soketinden dolayı RST'yi geri gönderir hala TIMEWAIT durumunda (SO_LINGER sıfır ile devre dışı bırakılmadıysanız, bu yüzden SO_LINGER değerini sıfır olarak ayarlamak istemiyorsunuz), sunucu soket durumu KAPALI olarak güncellenecektir.
  3. Sunucu, RST istemciden alındıktan sonra ikinci bir yazma girişiminde bulunursa, yazma başarısız olur.
  4. İstemci kapatıldıktan sonra sunucu bir geri çağırma girişiminde bulunursa, akış, akışı sonlandırmak için sıfıra geri döner.

O Özetle , o zaman sunucu olmasıdır (müşteri bağlantısını kapattı sonu akımı bildirimi bir işareti olarak recv() == 0 döndürülür kullanımı ve buna göre hareket ihtiyacı var demektir , ilgili soketi kapatın).

İlgili konular