2013-03-12 4 views
17

Jestem trochę zdezorientowany przez róg obfitości powiązanych metod na obiekcie Socket, który rzekomo zamyka i czyści połączenie przez gniazdo. Rozważmy następujący:Jaki jest właściwy sposób zamykania i czyszczenia połączenia z gniazdem?

var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
socket.Connect("192.168.1.22", 8333); 
socket.Send(Encoding.UTF8.GetBytes("hello")); 

// now for the closing fun 
socket.Shutdown(SocketShutdown.Both); 
socket.Disconnect(false); 
socket.Close(); 
socket.Dispose(); 

Ponadto this guy mówi, że aby naprawdę czysto zamknąć połączenie, należy wykonać socket.Shutdown(SocketShudown.Send), a następnie czekać na drugą stronę, aby odpowiedzieć.

Jaki jest prawidłowy sposób zamknięcia, a następnie wyczyścić połączenie gniazda?

+0

Ten facet ma połowę rację. Myślę, że to zależy od protokołu między tymi dwoma. Jeśli spodziewasz się, że będziesz w stanie odbierać przez pewien czas, to tak, powinieneś powiedzieć drugiej stronie o zamiarze zamknięcia i powiedzieć, że przestaniesz wysyłać, ale nadal możesz otrzymywać. – uriDium

+0

"ten facet" jest w większości poprawny, ponieważ podobnie modelowałem swój kod serwera. Uważam jednak, że podejście "półzbliżenie-potem-czekanie" jest konieczne tylko w przypadku asynchronicznych (nieblokujących) gniazd. Wierzę, że w przypadku gniazd nieblokujących, wywołujesz "Wyślij", a zaraz po tym Close, istnieją pewne warunki brzegowe, w których może nastąpić utrata danych, jeśli są pakiety, które muszą zostać ponownie przesłane. – selbie

+0

Użyłem podejścia hybrydowego z moim serwerem gniazd. Serwer najpierw zamknie połowicznie połączenie i poczeka, aż recv() zwróci 0 lub błąd, aby wskazać, że klient jest gotowy. Mam jednak zegar, który okresowo wyłącza się co 45 sekund, aby zamiatać i zamykać wszelkie półotwarte połączenia, które utrzymywały się od ostatniego przemiatania. – selbie

Odpowiedz

11

gniazdo zamknięcia zamyka połączenie i zamykania jest owinięcie wokół metoda-Zużyty, więc ogólnie

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

powinno wystarczyć. Niektórzy mogą twierdzić, że Close implementacja może się zmienić jednego dnia (więc już nie nazywa się Dispose), i powinieneś zadzwonić Dispose ręcznie po wywołaniu Close, ale wątpię, aby to się stało, osobiście :)

Alternatywnie, rozważ użycie przy użyciu (yeh):

using (var socket = new Socket(...)) 
{ 
    .... 
    socket.Shutdown(SocketShutdown.Both); 
}