2011-02-17 33 views
10

Moja aplikacja serwera używa TIdTCPServer, kilka aplikacji klienckich używa TIdTCPClients do łączenia się z serwerem (wszystkie komputery znajdują się w tej samej sieci LAN).Najlepsza praktyka: Pozostaw połączenie TCP/IP otwarte lub zamknij po każdym przesłaniu?

Niektórzy z klientów wystarczy skontaktować się z serwerem co kilka minut, inni raz drugi i jeden zrobi to około 20 razy na sekundę.

Gdybym utrzymać połączenia między klientem a serwerem otwartym, będę zapisać ponownie połączyć, ale trzeba sprawdzić, czy połączenie zostanie przerwane.

Gdybym zamknąć połączenie po każdym transferze, to musi ponownie łączyć za każdym razem, ale nie ma potrzeby, aby sprawdzić, czy połączenie jest nadal.

Jaki jest najlepszy sposób na zrobienie tego?

Przy jakiej częstotliwości przesyłania danych powinienem ogólnie utrzymywać połączenie otwarte?

Jakie są inne zalety/wady obu scenariuszy?

+3

Koszt nowego połączenia TCP to głównie kilka wizyt w obie strony. A te są dość szybkie w sieci LAN. Tak więc zamknęłbym połączenie po kilku sekundach nieużywania go. – CodesInChaos

+3

Ale napisałbym to w prosty sposób (najprawdopodobniej natychmiastowe zamknięcie) najpierw, a następnie sprawdź, czy wydajność jest zadowalająca. – CodesInChaos

+4

Zobacz moją odpowiedź na to pytanie: http://stackoverflow.com/questions/4872800/socket-open-and-close-on-1-sec-or-to-hold-open/4873002#4873002 –

Odpowiedz

8

Proponuję mieszankę dwóch. Gdy nowe połączenie zostanie otwarte, uruchom dla niego czas bezczynności. Po wymianie danych zresetuj licznik czasu. Jeśli upłynie czas, zamknij połączenie. Jeśli połączenie zostało zamknięte, gdy dane mają zostać wysłane, otwórz nowe połączenie i powtórz. W ten sposób mniej często używane połączenia mogą być okresowo zamykane, a coraz częściej używane połączenia mogą pozostać otwarte.

+0

Remy, dobra robota na Indy w ciągu ostatnich kilku lat ;-) Używam komponentów TCP Indy, i mam na myśli szeroko, jako nieodłączną część mojej rozproszonej struktury aplikacji. Możesz rzucić okiem na to. – Misha

6

Połączenie z aplikacją aktywną co kilka minut może być w porządku, jednak aplikacja, która komunikuje się kilka razy na sekundę, dostrzega zwiększenie wydajności, pozostawiając otwarte połączenie.

Ponadto Twój kod będzie bardzo prosty, jeśli nie będziesz próbował stale otwierać, zamykać ani diagnozować otwartego połączenia. Przy prawidłowej logice otwarcia i zamknięcia oraz SEH wokół odczytu i zapisu, nie ma powodu, aby sprawdzać, czy gniazdo jest jeszcze podłączone przed użyciem, po prostu go używaj. Pokaże ci, kiedy wystąpi problem.

Zachęcam do trzymania jednego połączenia otwartego w większości aplikacji dla przedsiębiorstw. Zwykle prowadzi to do czystszego kodu, który jest łatwiejszy do utrzymania.

/twocents

8

dwa centy od eksperymentu ...

mój pierwszy TCP/aplikacji klient/serwer IP używał nowego połączenia i nowego wątku dla każdego żądania ... lat temu ...

Wtedy odkryłem (używając ProcessExplorer), że consummed niektórych zasobów sieciowych, ponieważ wszystkie połączenia są zamknięte rzeczywiście nie zniszczone, ale pozostają w określonym stanie przez jakiś czas. Wiele wątków zostało stworzone ...

ja nawet miałem pewne problemy z połączeniem z wieloma concurent wniosków: Nie ma wystarczającej ilości portów na moim serwerze!

Tak I rewrote it, zgodnie ze schematem HTTP/1.1 i funkcją KeepAlive. Jest znacznie wydajniejszy, używa niewielkiej liczby wątków, a ProcessExplorer lubi mój nowy serwer. I nigdy więcej nie zabrakło mi portu. :)

Jeśli klient musi być zamknięcie, będę korzystać z puli wątków, aby przynajmniej nie stworzyć wątek na klienta ...

W skrócie: jeśli można przechowywać klienta połączenia żywe przez kilka minut.

3

Myślę, że wszystko zależy od celu i ilości wniosków złożonych na serwerze w danym momencie nie wspominając o dostępnej przepustowości i sprzętu na serwerze.

Musisz także myśleć o przyszłości, czy jest jakaś szansa, że ​​w przyszłości będziesz potrzebować połączeń, które pozostaną otwarte? jeśli tak, to odpowiedziałeś na własne pytanie.

Wdrożyłem system czatowy dla projektu, w którym ~ 50 osób (liczba rośnie z każdym 2-miesięcznym) jest zawsze połączony, a poza tym na czacie zawiera również transfer danych, manipulację bazą danych za pomocą określonych poleceń itd. Wdrożenie utrzymuje połączenie z serwerem otwarte od momentu uruchomienia aplikacji, dopóki aplikacja nie zostanie zamknięta, bez problemów, jednak jeśli połączenie zostanie utracone z jakiegoś powodu, zostanie automatycznie przywrócone i wszystko będzie działać bezbłędnie.

Podsumowując, sugeruję wypróbowanie obu (utrzymanie połączenia otwartego i zamknięcie po jego użyciu) i sprawdzenie, które najlepiej odpowiada Twoim potrzebom.

3

Jeśli nie skalujesz do setek równoczesnych połączeń, zdecydowanie utrzymam je otwarte - jest to zdecydowanie lepsze z dwóch opcji. Po przejściu od setek do tysięcy równoczesnych połączeń może zajść potrzeba zrzutu i ponownego połączenia. Skonstruowałem całą strukturę wokół tego (http://www.csinnovations.com/framework_overview.htm), ponieważ pozwala mi to "przesłać" dane do klienta z serwera, gdy jest to wymagane. Musisz napisać trochę kodu, aby upewnić się, że połączenie działa i działa (przerwy w sieci, czasowe pingi itp.), Ale jeśli zrobisz to w swoim "środowisku", to twój kod aplikacji może być napisany w taki sposób sposób, w jaki można założyć, że połączenie jest zawsze "up".

0

Problem stanowi ograniczenie liczby wątków na aplikację, około 1400 wątków. Tak więc maksymalnie 1300 klientów połączonych w tym samym czasie + -.

+0

Chociaż pulę wątków systemu operacyjnego wolałbym raczej zaimplementować na serwerach Indy (a nie na wątku klienta), to, co tutaj twierdzisz, jest nieprawidłowe - zobacz np. https://blogs.msdn.microsoft.com/oldnewthing/20050729-14/?p=34773 – Victoria

0

Podczas zamykania połączeń jako klient, używany port będzie niedostępny przez pewien czas. Tak więc przy dużej głośności używasz wielu różnych portów. Za wszystko, co powtarzalne, trzymam je otwarte.