2010-01-06 26 views
11

Bir tcp soketi için socket.Close() kullanılması, soketi tamamen kapatmıyor gibi görünüyor. Aşağıdaki örnekte açılmayan 9999 numaralı bağlantı noktasında example.com'a bağlanmaya çalışıyorum ve kısa bir zamanaşımından sonra soketi kapatmaya çalışıyorum.Soket.Close, tcp soketini gerçekten kapatmıyor mu? (C#)

TCP israel-xp:6506   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6507   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6508   www.example.com:9999 SYN_SENT 
    TCP israel-xp:6509   www.example.com:9999 SYN_SENT 

DÜZENLEME : döngü tamamlandıktan sonra netstat bakmak zaman

for (int i = 0; i < 200; i++) 
    { 
    Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    sock.LingerState = new LingerOption(false, 0); 
    sock.BeginConnect("www.example.com", 9999, OnSocketConnected, sock); 
    System.Threading.Thread.Sleep(50); 
    sock.Close(); 
    } 

Ama birçok yarı açılmış prizler olduğunu bulmak. Tamam, bazı bağlam eksik. Başlangıç ​​bağlantısı kullanıyorum çünkü soket bağlantısının başarısız olmasını bekliyorum (9999 açık değil) ve gerçek kodumda, bir zamanlayıcı ayarlandığında prizi çağıracağım.Close(). OnSocketConnected Üzerine EndConnect'i arayarak bir istisna atar (atılan nesnenin yöntemini çağırmaya çalışmak). Amacım soket bağlantı aşaması için kısa bir zaman aşımı yaşıyor.

Neyi yanlış yaptığımı bir ipucu? Teşekkürler!

cevap

14

Soketin .NET bölümünü kapatacaktır. Ancak, TCP belirtimine göre, işletim sistemi yeniden iletimi algılamak için benzer bir süre için soketin alt seviyedeki çerezlerini belirli bir süre açık tutmalıdır. Bu özel durumda, SYN paketine gönderilen bir cevabı algılamak için soketi biraz daha tutuyor olabilir, böylece daha duyarlı bir şekilde yanıt verebilir ve cevabı daha fazla paket ile karıştırmaz.

+2

bu mantıklı, ancak yalancı oyalama ayarlamamalı mı? – r0u1i

+0

oh, linger bunu yapmaz. Yani, Windows soketi sonlandırmak için gerçekten bir yol yoktur. – r0u1i

+1

varsayılan olarak, Windows gerçekten kapatmadan önce FIN_WAIT durumunda 4 dakika boyunca oturacaktır. Daha da ilginç olan ise, aynı hedef/port pencerelerine başka bir bağlantıyı tekrar açarsanız, eşleşen FIN_WAIT bağlantılarını yeniden kullanır. – Jay

10

*Begin*Connect numaralı telefonu arıyorsunuz - bu yüzden eşzamansız olarak çalışıyor. Soketi bile bağlamadan önce kapatmaya çalışıyorsunuz - o zaman bağlandığında açık kalır.

Eşzamanlı olarak bağlanmayı deneyin - ya da OnSocketConnected'da kapatın, böylece gerçekten bağlı bir soketin kapanmasının etkisini görebilirsiniz.

+0

Düzenleme bölümüne bakın. BeginConnect'i amaca yönelik kullanıyorum ve gerçek kodum, Close'u aramadan önce zaman aşımını bekler. EndConnect'i böyle bir sokette (dest portu açılmadığında) çağırmak sadece * uzun * bir zaman alacak. Ya da başka bir deyişle, X milisaniye sonra soket bağlantı aşamasını zaman aşımına uğramak istiyorum (ve milisaniye pencerelerinin absürdisi sayısı varsayılan olarak değil).Jon Skeet'in cevabı hakkında yorum için – r0u1i

18

Tasarım gereği, soketi kapatmadan önce her zaman Shutdown numaralı telefonu aramalısınız. böylece etkili bir şekilde yapmak

mySocket.Shutdown(SocketShutdown.Both); 
mySocket.Close(); 

göndermek ve soket üzerinde almak devre dışı bırakır, böylece işletim sistemi hala onun kontrolünü sahip olsa bile, bunu kapattıktan sonra gelen verileri kabul edilmeyecektir.

Jon Skeet ayrıca, bağlantıyı eşzamansız olarak açtığınız için, kapatmaya çalışırken bağlantı kurabilmenizin de bir anlamı vardır. Ancak, üzerinde Shutdown numaralı telefonu ararsanız, karşılaştığınız gibi bilgilerin alınmasına izin verilmez.

Düzenleme: Eğer kod yazarken Yalnızca Shutdown zaten bağlı olan bir yuva, bu nedenle bu akılda olabilir.

+0

+1. :-) –

+0

ShutDown, soket henüz bağlanmadıysa, tam olarak benim senaryo olduğumda bir deneme atıyor. – r0u1i

+0

O zaman OnSocketConnected öğesini ShutDown öğesini çağırmak ve kapatmak ya da bu tür bir şeyi kapatmak için kullanmalısınız. –

0

Her Döngü'de yeni bir Yuvaya başlıyorsunuz ... * .close() ile eskiyi kapatırsınız ve daha önce Soket ile aynı parametrelerle yeni bir tane oluşturmaya başlarsınız.

+0

evet. ama bir tane olmaktan çok daha fazla açık yuva görüyorum. – r0u1i

İlgili konular