Czy UDP jest wciąż lepszy niż TCP w przypadku gier zawierających duże ilości danych?

71

Wiem, że UDP jest zwykle zalecane w przypadku gier wieloosobowych w czasie rzeczywistym z dużym wykorzystaniem danych.

Większość artykułów ma wiele lat, a ponieważ około 80% wszystkich danych przesyłanych w Internecie to TCP, wiele zostało zoptymalizowanych pod kątem TCP.

To mnie zastanawia: czy UDP wciąż jest lepszy pod względem szybkości i opóźnień? Czy ostatnie optymalizacje TCP spowodowały, że TCP działał lepiej niż UDP?

KaareZ
źródło
25
Dzięki UDP nie ma gwarancji, że twoje pakiety zostaną odebrane lub nawet zamówione, co samo sprawia, że ​​UDP jest szybszy niż TCP.
nathan
4
@Kareare, co masz na myśli szybsze wdrożenie?
nathan
2
@nathan Że łatwiej jest tworzyć aplikacje za pomocą TCP niż UDP. Chcę wiedzieć, czy wszystkie optymalizacje TCP spowodowały, że TCP jest lepszą opcją pod względem wydajności.
KaareZ 18.04.16
3
@Karez nie jestem ekspertem, ale pomyślmy o tym. Jak TCP może być lepszy pod względem wydajności i nadal być niezawodnym protokołem? Nie możesz mieć wszystkiego. TCP jest stworzony dla niezawodności. Prawdziwe pytanie brzmi: dlaczego chcesz używać TCP w swojej grze?
nathan
7
UDP jest lepszy niż TCP tylko wtedy , gdy jesteś w stanie (= doświadczony programista sieciowy niskiego poziomu) ponownie wdrożyć tylko funkcje TCP, których potrzebujesz w nim skutecznie. Usunięcie niepotrzebnych funkcji TCP w celu zwiększenia wydajności.
wondra 18.04.16

Odpowiedzi:

119

Nie, UDP wciąż jest lepszy pod względem opóźnień w wydajności i zawsze będzie szybszy, ze względu na filozofię dwóch protokołów - zakładając, że dane komunikacyjne zostały zaprojektowane z myślą o UDP lub innej komunikacji stratnej.

TCP tworzy abstrakcję, w której docierają wszystkie pakiety sieciowe i docierają w dokładnie takiej kolejności, w jakiej zostały wysłane. Aby zaimplementować taką abstrakcję na kanale stratnym, musi ona zaimplementować retransmisje i limity czasu, które pochłaniają czas. Jeśli wyślesz 2 aktualizacje przez TCP, a pakiet pierwszej aktualizacji zginie, nie zobaczysz drugiej aktualizacji, dopóki:

  1. Wykryto utratę pierwszej aktualizacji.
  2. Wymagana jest ponowna transmisja pierwszej aktualizacji.
  3. retransmisja dotarła i została przetworzona.

Nie ma znaczenia, jak szybko odbywa się to w TCP, ponieważ dzięki UDP po prostu odrzucasz pierwszą aktualizację i używasz teraz drugiej, nowszej. W przeciwieństwie do TCP, UDP nie gwarantuje, że wszystkie pakiety dotrą i nie gwarantuje, że dotrą w kolejności.

Wymaga to wysłania właściwego rodzaju danych i zaprojektowania komunikacji w taki sposób, aby utrata danych była możliwa do zaakceptowania.

Jeśli masz dane, do których musi dotrzeć każdy pakiet, a Twoja gra musi przetwarzać pakiety w kolejności, w jakiej zostały wysłane, UDP nie będzie szybsze. W rzeczywistości użycie UDP w tym przypadku byłoby prawdopodobnie wolniejsze, ponieważ rekonstruujesz TCP i implementujesz go za pomocą UDP, w którym to przypadku równie dobrze możesz użyć TCP.

EDYCJA - Dodanie dodatkowych informacji w celu włączenia / rozwiązania niektórych komentarzy:

Zwykle wskaźnik utraty pakietów w sieci Ethernet jest bardzo niski, ale staje się znacznie wyższy po włączeniu Wi-Fi lub w trakcie przesyłania / pobierania przez użytkownika. Załóżmy, że mamy idealnie jednolitą utratę pakietów wynoszącą 0,01% (w jedną stronę, a nie w obie strony). W strzelankach FPS klienci powinni wysyłać aktualizacje za każdym razem, gdy coś się stanie, na przykład gdy kursor myszy obróci odtwarzacz, co dzieje się około 20 razy na sekundę. Mogą także wysyłać aktualizacje na ramkę lub w ustalonych odstępach czasu, co będzie wynosić 60-120 aktualizacji na sekundę. Ponieważ aktualizacje te są wysyłane w różnych momentach, będą / powinny być wysyłane w jednym pakiecie na aktualizację. W grze 16-osobowej wszyscy 16 graczy wysyła te 20-120 pakietów na sekundę do serwera, co daje w sumie 320-1920 pakietów na sekundę. Przy naszym współczynniku utraty pakietów wynoszącym 0,01% spodziewamy się utraty pakietu co 5,2-31,25 sekundy.

Na każdym pakiecie, który otrzymamy po zgubionym pakiecie, wyślemy DupAck, a po 3. DupAck nadawca ponownie wyśle ​​utracony pakiet . Tak więc czas wymagany przez TCP do zainicjowania retransmisji wynosi 3 pakiety, plus czas, jaki musi upłynąć, zanim ostatni dupAck dotrze do nadawcy. Następnie musimy poczekać, aż nadejdzie retransmisja, więc w sumie czekamy 3 pakiety + 1 opóźnienie w obie strony. Opóźnienie w obie strony wynosi zwykle 0-1 ms w sieci lokalnej i 50-200 ms w Internecie. 3 pakiety zwykle docierają w ciągu 25 ms, jeśli wyślemy 120 pakietów na sekundę, i w 150 ms, jeśli wyślemy 20 pakietów na sekundę.

W przeciwieństwie do UDP, odzyskujemy utracony pakiet, gdy tylko otrzymamy następny pakiet, więc tracimy 8,3 ms, jeśli wysyłamy 120 pakietów na sekundę, i 50 ms, jeśli wysyłamy 20 pakietów na sekundę.

W przypadku protokołu TCP sytuacja staje się coraz bardziej skomplikowana, jeśli musimy również rozważyć Nagle (jeśli programista zapomni wyłączyć wysyłanie koalescencji lub nie może wyłączyć opóźnionego potwierdzenia ACK ), unikania przeciążenia sieci lub jeśli utrata pakietów jest na tyle poważna, że ​​musimy uwzględnić wiele straty pakietów (w tym utracone Ack i DupAck). Dzięki UDP możemy łatwo pisać szybszy kod, ponieważ po prostu nie dbamy o to, aby być dobrym obywatelem sieci, tak jak TCP.

Piotr
źródło
Uwaga: UDP może transmitować sieć lokalną (możliwa zaleta), a ponieważ Vista wymaga od administratora uruchomienia serwera / emisji na UDP (wada) (UAC / zapora sieciowa zwykle nie informuje, że wymagane jest działanie użytkownika).
PTwr
7
„Jeśli wyślesz 2 aktualizacje za pośrednictwem protokołu TCP, a pakiet pierwszej aktualizacji zostanie utracony” Prawda, ale jakie są szanse na to? Według pingmana :
mucaho 18.04.16
30
@Peter zapominasz, że w TCP każdy upuszczony pakiet zatrzymuje się na każdym kolejnym pakiecie. Przy pingu 100 ms może to być 300-500 ms, zanim pakiet zostanie ponownie przesłany i odebrany, więc jest to 6-10 pakietów, które są blokowane co 33 sekundy. Z pewnością będzie to zauważalne w trzęsieniu ziemi FPS.
BlueRaja - Danny Pflughoeft 18.04.2016
12
W wielu implementacjach TCP pierwszy limit czasu po nieudanym potwierdzeniu zajmie pełną sekundę. To długo . Jeśli pakiety są małe, UDP może łatwo wygładzić brakującą transmisję lub dwie, po prostu uwzględniając każdy pakiet zawierający dane z dwóch ostatnich aktualizacji, aby aplikacja otrzymała dane, których potrzebuje, zanim nadawca lub odbiorca dowie się, że zaginął pierwszy pakiet.
supercat 18.04.16
23
W przypadku gry takiej jak Quake utrata pierwszego pakietu nie ma znaczenia. W FAR krócej niż czas zajęłoby ci wykrycie straty i retransmitacja pierwszego pakietu, powinieneś już przesłać drugi pakiet, co powoduje, że pierwszy i tak staje się przestarzały. Jest to ten sam powód, dla którego wiele aplikacji głosowych i wideo w czasie rzeczywistym również korzysta z UDP. Jeśli pakiet zostanie upuszczony, wolisz po prostu stracić 0,02 sekundy dźwięku niż opóźnić cały strumień o pełną sekundę lub dłużej. To samo ogólnie dotyczy gier w czasie rzeczywistym, ponieważ chcesz wiedzieć, gdzie jest teraz obiekt , a nie 1,5 sekundy temu.
reirab
19

Zgadzamy się, że zarówno TCP, jak i UDP są protokołami zbudowanymi na bazie IP , prawda? IP określa sposób dostarczania wiadomości przez Internet, ale nic nie dotyczy struktury, formatu wiadomości. Nadchodzą protokoły TCP i UDP. Korzystają z właściwości IP, ale pozwalają programiście skupić się na wymianie komunikatów bez martwienia się o niższe warstwy komunikacji sieciowej. I to świetnie, ponieważ bezpośrednia obsługa sygnałów analogowych w przewodach byłaby trochę bolesna.

  • TCP zapewnia zestaw funkcji do wysyłania i odbierania wiadomości. Dzieli nasze dane na małe pakiety dla siebie i wysyła je przez sieć. Jedyne, o co nas prosi, to port do użycia przez gniazdo sieciowe i faktyczna wiadomość, którą chcemy wysłać. Jest także niezawodny, co oznacza, że ​​jeśli niektóre pakiety zostaną utracone w sieci, zostaną wykryte, a następnie wysłane ponownie, dbając o wysyłkę w tej samej kolejności, w jakiej miały dotrzeć.

  • Z drugiej strony UDP jest protokołem zorientowanym na kontrolę użytkownika. Używając UDP do wysyłania naszych datagramów , nie możemy być pewni, czy datagram kiedykolwiek dotrze do miejsca docelowego, czy nie (i mamy na myśli matematyczną pewność: kiedy wysyłamy pakiet, najprawdopodobniej dotrze, ale nie możemy być pewni 100%). Ponadto, gdy pakiet zostanie utracony, nie zostanie wykryty ani wysłany ponownie.

W tym momencie TCP wyglądałby jak idealne rozwiązanie wszystkich naszych problemów. Jest niezawodny, szybki, rozwiązuje dla nas opóźnienie połączenia, śledząc, które pakiety przybyły i jakie pakiety nadal musimy wysłać.

ALE , patrz dalej. Jedyną zaletą, jaką zapewnia nam UDP, jest szybkość, i właśnie to jest jedna z rzeczy, której naprawdę chcemy. Pakiet UDP jest właśnie spreparowany, sprawdzany i wysyłany bez żadnych szczególnych kontroli, ponieważ tak działa protokół UDP. Pakiet TCP musi zostać spreparowany, oznaczony, sprawdzony, a kiedy nadejdzie, zostanie wysłane potwierdzenie ACK z informacją dla nadawcy „pakiet x jest tutaj, kontynuuj” , a gdy ten sygnał nie zostanie wysłany, oznacza to, że taki pakiet x musi zostać wysłany jeszcze raz.

Wiem, że UDP jest zwykle zalecane w przypadku gier wieloosobowych w czasie rzeczywistym z dużym wykorzystaniem danych.

Tak, ale nie tylko. UDP jest bardziej preferowany niż TCP, głównie dlatego, że jego duża szybkość jest idealna do obsługi wysyłania i zarządzania wysokimi danymi. Dzieje się tak, gdy przy założeniu, że taka gra wideo działa na deterministycznej blokadzie (to, co dzieje się na serwerze, jest identycznie replikowane na dowolnym kliencie niezależnie od opóźnienia sieci), pakiet aktualizacyjny zostaje utracony i nigdy nie dociera do miejsca docelowego. TCP ponownie wyśle ​​taki pakiet, a kolejne pakiety zostaną odrzucone, ponieważ nie dotrą w kolejności, a następnie zostaną ponownie wysłane po zgubionym. UDP jest znacznie bardziej tolerancyjny w tym scenariuszu: nie będzie dbał o ten pakiet, ponieważ nadchodzą nowsze aktualizacje. Utracona aktualizacja nie jest renderowana, zamiast tego fizyka gry jest interpolowana w zależności od zastosowanej metody integracji i najnowszej otrzymanej aktualizacji.

TCP powoduje drgania, gdy opóźnienie jest wystarczająco duże, UDP nie:

<video style="min-width: 100% height: auto" autoplay="" preload="auto" loop="true"><source src="https://gafferongames.com/videos/deterministic_lockstep_tcp_250ms_5pc.mp4" type="video/mp4"><source src="http://173.255.195.190/cubes_deterministic_lockstep_tcp_250ms_5pc.webm" type="video/webm">Your browser does not support the video tag.</video>

To sprawia, że ​​zastanawiam się, czy UDP nadal jest lepszy pod względem szybkości i opóźnień.

Tak, tak jest i będzie przez długi czas. Możesz przeczytać więcej o TCP vs UDP tutaj .

liggiorgio
źródło
8
TCP używa strumieni bajtów zamiast datagramów. UDP korzysta z datagramów. Dobre implementacje TCP utrzymają pakiety przychodzące poza kolejnością, ale żadna zawartość pakietu nie może zostać udostępniona aplikacji, dopóki wszystkie poprzednie pakiety nie zostaną odebrane. Zatem jeśli jeden pakiet zostanie zgubiony, nadawca może nie być zmuszony do ponownego przesłania wszystkiego, co nastąpiło po zgubionym pakiecie, ale aplikacja odbierająca nie zobaczy niczego poza utraconym pakietem, dopóki pakiet nie zostanie ponownie przesłany (po czym aplikacja natychmiast zobaczy zawartość tego pakietu) pakiet i kolejne).
supercat
@ superuper Niestety, TCP nie ma sposobu, aby powiedzieć nadawcy dokładnie, które pakiety wysłał i nie otrzymał. Ma tylko mechanizm „Otrzymałem wszystkie bajty do x numeru porządkowego”. Jeśli nadawca retransmituje pakiety, które odbiorca już otrzymał, po prostu zignoruje kopie.
reirab
@reirab: Myślałem, że są pewne nowoczesne rozszerzenia, które zawierały tę funkcję, choć nawet bez tego uważam, że implementacja, która wysłała dane do bajtu # 1 050 000, ale otrzymała tylko paczki danych do 1 000 000, po sekundzie bez słyszenia każde potwierdzenie dotyczące czegoś powyżej 1.000.000, zacznij od wysłania bloku danych od 1.000.000 do 1.000.500, a następnie czekając na odpowiedź. Jeśli otrzyma potwierdzenie dla danych do 1.000.500, może następnie retransmitować więcej danych; jeśli otrzyma potwierdzenie dla danych do 1 050 000, może pominąć retransmisje.
supercat 18.04.16
1
@Giorgio IP nic nie określa na temat sygnałów analogowych. Odbywa się to na warstwie fizycznej. IP działa o dwie warstwy powyżej tej w warstwie sieci. IP nie może mniej obchodzić, czy bity są przesyłane przez światłowód, łącze satelitarne, czy modem telefoniczny 14,4 kb / s. UDP i TCP to warstwa wyższa od IP w warstwie transportowej. Ponadto, jak mówi supercat, TCP przedstawia interfejs strumieniowy aplikacji, a nie interfejs datagramowy taki jak UDP.
reirab
@ supercat Hmm ... możesz mieć rację co do nowoczesnych rozszerzeń, choć z pewnością nie jest to część oryginalnego standardu TCP. ACK ma po prostu numer sekwencyjny. Zakładam, że implementacja TCP normalnie rozpoczyna retransmisję całego okna wysyłania, jeśli pakiet zostanie upuszczony, zamiast czekać na cały RTT dla każdego pakietu. Zwiększyłoby to opóźnienie, gdyby kilka kolejnych pakietów zostało utraconych przy bardzo niewielkim zysku.
reirab
9

TCP <- protokół kontroli transmisji . Służy do sterowania transmisją.

TCP został stworzony, aby być dobrym obywatelem sieci dyplomatycznej. Koncentruje się na tym, aby networking był dobrym doświadczeniem dla wszystkich i chętnie zmniejsza jego przepustowość, aby to osiągnąć. To dostosowuje się do środowiska przez dodanie opóźnienia . Przyczyny są na przykład:

  • Odbiorca wykrywa brakujący pakiet, informuje nadawcę, aby zwolnił (o połowę zmniejszyć szybkość).
  • Odbiornik wykrywa niewłaściwą kolejność przychodzących pakietów (być może wybrał różne ścieżki sieciowe), informuje nadawcę, aby zwolnił - i tak dalej, odbiorca nie przyjmie kolejnych pakietów, dopóki nie pojawi się brakujący. Zajęcie się tym zajmuje dużo czasu.
  • Nadawca wykrywa przeciążenie sieci (np. Wolny czas okrążenia), zwiększa opóźnienie.
  • Odbiornik nie może nadążyć za prędkością (bufor wejściowy się zapełnia), prosi nadawcę o dodanie opóźnienia (kontrola przepływu).
  • Istnieje jeden wolny odbiornik (wysoki ping drań, crybaby, jak to się nazywa) wśród odbiorników, opóźnienie (może być) dodane w gospodarstwie domowym.

do tego

  • Algorytm Nagle może zatrzymać dane nadawców, dopóki nie będzie więcej do wysłania (w celu bardziej efektywnego wykorzystania ramek danych). Dane krytyczne czasowo ulegają opóźnieniu.
  • Wierzę, że zwykłe routery domowe z wlanem mogą robić inteligentne rzeczy (spowalniać), aby wygładzić przepustowość TCP między wieloma klientami (interfejs wlan jest wąskim gardłem, nawet jeśli gra go nie używa). Odnosi się do emisji / multiemisji, tj. „inne” dane mogą zmniejszyć przepustowość TCP.
  • TCP AC Potwierdza wszystko, co nie jest konieczne w środowisku gier. Potwierdzanie każdej aktualizacji fizyki nie ma sensu. Wystarczy, aby potwierdzić, na przykład raz na sekundę lub podobnie. Jeśli klient (lub serwer) milczy przez dłuższy czas, czas na reakcję.

Mimo to TCP zapewnia najwyższą wartość dla (ogólnie przesyłanych danych) / (całkowitego zużytego czasu). Tyle, że nie dzieje się to dokładnie wtedy, gdy tego chcesz.

UDP nie robi żadnej z nich. Wystrzeliwuje na twoją wolę, tyle że nie można oczekiwać, że trafi za każdym razem - bez względu na to, że cel musi ogłosić, że „od dawna nie strzelałeś, dlaczego?”. Nadal można tworzyć własne pakiety ACK, umieszczać wiele rekordów w jednym pakiecie itp. Ważne jest także kontrolowanie przejścia NAT. UDP z pewnością nadaje się do gier o niskim opóźnieniu.

Stormwind
źródło
1
Uwaga: algorytm Nagle można wyłączyć, np. Dla systemu Linux .
mucaho 18.04.16
Nagle może działać przeciwko (i można go ominąć, ustawiając każdy pakiet na „wypychanie” przez aplikację), tymczasem Opóźniony Ack działa na korzyść TCP, pozwala nadawcy umieścić więcej bajtów na kablu, aż okno wysyłania będzie pełne (najlepiej tak duże ponieważ bufor odbiorczy znajduje się po drugiej stronie), niezależnie od tego, czy potwierdzenie zostało zauważone.
Jeff Meden,
4
To protokół kontroli transmisji .
ysdx 19.04.16
1
Wpisz te słowa milion razy ... thx - naprawione.
Stormwind,
3

Możesz porównać pierwszy schemat RFC 768 (UDP) z pierwszym schematem RFCP 793 (TCP) strona 15 .

Oba pokazują 16 bitów dla „portu źródłowego”, a następnie 16 bitów dla „portu docelowego”. Oba pokazują 16 bitów dla „sumy kontrolnej”. Zgodnie z RFC 768 „procedura sumy kontrolnej UDP jest taka sama jak w TCP”.

Podczas gdy długość UDP podsumowuje szczegóły diagramu UDP, długość TCP jest częścią „96-bitowego pseudo nagłówka” opisanego na stronach 15 i 16.

Nie oczekuj, że TCP osiągnie lepsze wyniki niż UDP. To po prostu mało prawdopodobne z wielu powodów. Jednym z nich jest to, że TCP ma po prostu więcej bitów. Jeśli więc sprzęt może skutecznie przetwarzać pewną liczbę bitów na sekundę, pozwoli to na większą liczbę pakietów UDP niż pakietów TCP.

Innym powodem jest to, że „potrójny uścisk dłoni” TCP oznacza, że ​​nadawca musi czekać na odpowiedź. To wymaganie wprowadza dodatkowy narzut, którego UDP nie obsługuje. Istnieje powód, dla którego większość komunikacji internetowej zaczyna się od komunikacji UDP. Podstawowy DNS korzysta z protokołu UDP, ponieważ żądanie i odpowiedź można wykonać w mniejszej liczbie kroków niż proces „potrójnego uzgadniania” protokołu TCP. Funkcja śledzenia utraconych pakietów przez TCP jest raczej nieciekawa, ponieważ komputer może po prostu wysłać nowe żądanie, zamiast próbować powiadomić zdalny system o niespełnieniu wcześniejszego żądania.

TOOGAM
źródło
Chociaż angielskie streszczenia (jak widać w niektórych innych odpowiedziach) są ładne, po prostu dokładne i precyzyjne opisy mogą być najprostsze.
TOOGAM
Masz na myśli 16 bitów, a nie bajtów!
jcaron 21.04.16
Och, głupie ja. to przykład, dlaczego precyzyjne technicznie odpowiedzi są ładne; łatwo je zidentyfikować i zobaczyć prawidłowe informacje. Naprawiłem odpowiedź. Dziękuję @jcaron
TOOGAM
2

Zastanów się, co się dzieje przez chwilę. Aby uprościć scenariusze, masz dwie możliwości, kiedy próbujesz wysłać zmianę stanu (np. Twój gracz właśnie zmienił kierunek, strzelił z pistoletu lub inny gracz właśnie wystrzelił bombę):

  1. Pozostaw sesję TCP otwartą, a kiedy bomba ma wybuchnąć, wyślij wiadomość TCP do wszystkich graczy (jeśli to możliwe, patrz poniżej)
  2. Słuchaj portu UDP, a kiedy bomba ma wybuchnąć, wyślij wiadomość UDP do wszystkich graczy bez względu na ich stan połączenia

Zakładając, że tuż przed nim nie była potrzebna aktualizacja, czas, w którym ta pojedyncza aktualizacja pojawi się w wersji 1 na 2, nie będzie zupełnie inny. To jedna podróż z serwera do klienta. Ale powiedzmy, że zamiast wybuchu bomby próbujesz nieustannie przekazywać informacje o aktywności osoby biegającej przez labirynt; tkanie, nurkowanie, strzelanie itp. W przypadku UDP każda czynność zostanie wysłana do datagramu, gdy tylko się to stanie. W przypadku TCP każda akcja zostanie wysłana w pakiecie tylko wtedy, gdy serwer będzie mógł wysłać. Co mówi, że można wysyłać? Mając miejsce w oknie TCP (zakładając, że opóźnione potwierdzenie jest aktywne), aby wiadomość mogła zostać umieszczona na kablu. Jeśli nie, musi poczekać na potwierdzenie od klienta przed wysłaniem.

Jak długo jest za długi? Gdy gra wieloosobowa w strzelanki FPS zaczęła działać w późnych latach 90-tych, połączenia o niskim opóźnieniu na początku 2000 roku nie były powszechne. Modem telefoniczny miałby typowe opóźnienie w jedną stronę 180 ms. Czekanie na potwierdzenie przed wysłaniem kolejnej aktualizacji, skutecznie podwajającej ten czas do 360 ms, było bolesne; nawet początkujący użytkownicy z pewnością odczuwają różnicę. Gdy połączenia szerokopasmowe zostały złapane, znacznie zmniejszyły opóźnienie, ale nadal występowało, gdy przepustowości brakowało (dość często w niektórych obszarach). Tak więc utrzymała się preferencja dla możliwie najniższego opóźnienia.

Nowoczesne połączenia domowe i połączenia zmieniły to do tego stopnia, że ​​regionalne opóźnienia, nawet w zatłoczonych porach dnia, mieszczą się w zakresie 15 ms lub poniżej. Wybór TCP zamiast UDP byłby w większości przypadków niewidoczny, ponieważ opóźnienie jest „wystarczająco małe”. Jednak nadal istnieje tendencja do nadawania priorytetu UDP nad TCP, biorąc pod uwagę jego historię jako protokół o niskim opóźnieniu. Tak więc, na razie (i prawdopodobnie w przyszłości) UDP będzie preferowany do komunikacji w czasie rzeczywistym.

Jeff Meden
źródło
Opóźnienie byłoby wystarczająco małe, z tym wyjątkiem, że domyślnie zapisy TCP są wysyłane tylko wtedy, gdy dane do zapisu przekroczą pewien próg lub upłynie limit czasu (zwykle 200-1000 ms). Jeśli potrzebujesz protokołu TCP w systemie o niskim opóźnieniu i małej przepustowości, musisz wyłączyć tę funkcję i upewnić się, że nie zapisujesz poszczególnych bajtów przez cały czas (np. Nie traktujesz już strumienia TCP jako strumienia i udajesz, że zamiast tego zajmują się poszczególnymi wiadomościami). Nie musisz czekać na potwierdzenie, chyba że twoje bufory są pełne, co jest raczej mało prawdopodobne w typowej grze w czasie rzeczywistym.
Luaan 19.04.16
1
@Luaan Enter: flaga TCP PSH. Gdy aplikacja przekazuje go do stosu, pakiet jest wysyłany natychmiast, bez oczekiwania na więcej danych. Wiele aplikacji korzysta z tego z powodzeniem (na przykład telnet i ssh).
Jeff Meden,
2

Wiem, że UDP jest zwykle zalecane w przypadku gier wieloosobowych w czasie rzeczywistym z dużym wykorzystaniem danych.
Czy UDP jest nadal lepszy pod względem szybkości i opóźnień? Czy ostatnie optymalizacje TCP spowodowały, że TCP działał lepiej niż UDP?

Twoje założenia są błędne. TCP i UDP różnią się przede wszystkim tym, jaki model reprezentują (niewiarygodne datagramy w porównaniu z niezawodnym wirtualnym strumieniem w kolejności).

Nie różnią się pod względem wielkości („duże zużycie danych”) ani przepustowości. TCP przepchnie tyle samo danych co UDP, z łatwością nasyci fizyczny kabel.

W przypadku utraty pakietów oba różnią się opóźnieniem, ale tylko w tym stanie. W przeciwnym razie TCP ma tak samo małe opóźnienie jak UDP (daj lub weź może kilkadziesiąt nanosekund, ponieważ stos sieciowy ma nieco więcej logiki do zrobienia, ale to raczej nieistotne).
Istnieje niewielka różnica w rozmiarze nagłówka, więc technicznie więcej bajtów musi przejść przez drut na liniach szeregowych, ale ten też jest raczej nieistotny. To naprawdę ma znaczenie tylko w przypadku przelewów masowych, a wtedy różnica wynosi około 0,5%. Większość osób z domowym dostępem do Internetu DSL kieruje cały ruch przez bankomat, co stanowi ponad 10% narzutu protokołu (5 bajtów kontrolnych na 48 bajtów ładunku plus częściowe ramki) i nikt nawet tego nie zauważa.

Niektóre osoby budują niezawodność oprócz UDP. Jeśli pożądany jest pewien poziom niezawodności, ale ścisłe dostarczanie w kolejności nie jest potrzebne, może to dać niewielką przewagę. Nadal jednak jest dyskusyjne, czy to podejście ma sens, a za tę niewielką przewagę płaci się wysoką cenę.
Jeśli masz klientów łączących się z hotelowym WiFis lub innymi „dziwnymi” miejscami, zauważysz, że często ogólna obsługa protokołu TCP jest znacznie, znacznie lepsza niż w przypadku UDP.

Gry na ogół używają UDP nie dlatego, że jest lepszy na jeden z wyżej wymienionych sposobów - nie jest - lub dlatego, że można zmniejszyć jitter o pół milisekundy poprzez wdrożenie niezawodności bez kolejności, ale dlatego, że gry (podobnie jak telefonia IP) często zawierają wiele bardzo niestabilnych danych, takich jak na przykład aktualizacje pozycji.
Te niestabilne dane są regularnie i szybko tracone na aktualności, zarówno z upływem czasu, jak i następnego nadchodzącego datagramu. Co oznacza nic więcej i nic mniej niż to, że tak naprawdę nie zależy ci zbytnio na byciu w 100% niezawodnym (lub uporządkowanym).

Zakładając, że pakiet sieciowy jest upuszczany w usłudze, która działa w stałym tempie z częstymi aktualizacjami (strzelanka, telefon, czat wideo), nie ma sensu mieć czasu potwierdzenia i ponownie wysłać pakiet, a tymczasem zatrzymaj wszystko na drugim końcu, czekając na nadejście wysłanego pakietu. To zbyt niepokojące i nic dobrego.

Zamiast tego, po prostu uważasz, że pakiet został utracony i przejdź dalej, biorąc dane z następnego pakietu, który je przeszedł, a tymczasem, najlepiej jak potrafisz, ukryj fakt, że pakiet został utracony przez użytkownika. Interpolacja, martwe obliczanie, ty to nazwij.

Zauważ, że utrata pakietów jest normalnym stanem. Podczas gdy IP jest ogólnie „dość wiarygodne”, pakiety czasami może zdarzyć się przed upadkiem, a będzie się działo . Chociaż utracone pakiety zwykle występują raczej rzadko (tutaj <1%), nie jest to nic nadzwyczajnego ani teoretycznego, ani wskazanie, że coś jest zepsute. To jest całkowicie normalne.
Każdy masowy transfer TCP musi na przykład zawierać utracone pakiety (tak działa kontrola przeciążenia).

Damon
źródło
2

W MPG o dużej przepustowości nie przejmujesz się, że przegapiłeś pakiet, który podaje lokalizację i zdrowie potwora # 425, ponieważ za ułamek sekundy otrzymasz kolejną aktualizację. To jest przykład, w którym UDP sprawia, że ​​TCP wygląda głupio, gdy trzeba czekać na natychmiastowo przestarzałe dane.

W tej samej grze chcesz, aby łatki były wyświetlane dokładnie tak, jak zostały zaprojektowane. TCP ma już wbudowane funkcje „powiedz mi, jeśli się nie uda”, co ułatwia automatyczne ponawianie prób i sprawdzanie błędów. Możesz to zrobić w UDP, ale po co odtwarzać technologię?

Oto prosty opis tego, co się dzieje.

UDP - Izoluj fragment O'data.
Zrób pakiet.
Encapsulate in IP.
Wyślij to.

TCP - izoluj strumień O'data.
Zrób pakiet z przodu strumienia.
Encapsulate in IP.
Poczekaj na miejsce w oknie TCP.
Wyślij to.
Wysyłaj dalej do momentu otrzymania potwierdzenia lub przekroczenia limitu czasu.
Pozostań w oknie TCP do momentu otrzymania potwierdzenia lub przekroczenia limitu czasu.

Wysyłka oznacza po prostu, że dotarła przez lokalną kartę sieciową, nie więcej.

Odbiór paragonów TCP gwarantuje odbiór danych i zwalnia miejsce w oknie na następny pakiet.

Ponowne wysłanie (nieznacznie) zwiększa prawdopodobieństwo ostatecznego otrzymania.

Pakiety TCP są ponownie składane po drugiej stronie jako uporządkowany strumień danych. Pakiety UPD są odbierane jako odrębny pakiet. Protokół nie zachowuje porządku.

TCP jest dobry do przesyłania wymaganych danych i dużych uporządkowanych ilości danych. TCP zapewnia powiadomienie o trwałej awarii. TCP samoczynnie dławi się przez zadławione rury (patrz: okno). TCP ma uściski dłoni, aby spowolnić inicjalizację. TCP wymaga „połączenia” przed transmisją.

UDP po prostu umieszcza dane na kablu i pozwala kontynuować bez czekania na okna i retransmisje. UDP wysyła dane z pełną prędkością do zadławionej rury, bez względu na to, ile danych zostanie utraconych.

Zaprojektowałem i napisałem komercyjne narzędzie UDP Multicast File Transport Utility. Pracowałem nad stosami IP. To tylko podstawy, bez minut. Wyjaśnienie „gniazd, MTU i innych zabawnych zabawek” było nieco poza tym, co byłoby przydatne w tym pytaniu.

Ps (nie mogę dodawać komentarzy, aby odpowiedzieć na komentarze) UDP nadaje się również do danych, które są pożądane, ale nie wymagane. Forward Error Correction jest przykładem tego, wielu niepotrzebnych, ale pożądanych pakietów.

dusc2don
źródło
3
Twoje zdanie na temat „przestarzałych” danych jest dobre. TCP jest dobry dla danych „lepiej późno niż nigdy”, ale UDP jest dobry dla danych, które będą przydatne, jeśli szybko dotrą do miejsca docelowego, ale bezużyteczne, jeśli nie.
supercat 18.04.16
1

Czy wszystkie zoptymalizowane routery TCP sprawiły, że TCP działa lepiej niż UDP?

Kolejne pytanie brzmi: czy „duże obciążenie danych” oznacza, że ​​często ładujesz sceny?

Jeśli tak, może być konieczne intensywne wysyłanie dużych fragmentów danych (> 1k), w których protokół TCP może być znacznie bardziej wydajny, ponieważ szczególnie po stronie serwera karty sieciowe zapewniają różne odciążenia o takiej samej liczbie cykli. Aplikacja przestrzeni użytkownika może generować duże zapisy przy użyciu protokołu TCP, podczas gdy w UDP próba wysłania bajtów o rozmiarze większym niż nagłówki MTU spowoduje fragmentację adresu IP i inne koszty ogólne, które spowodują spadek wydajności

Vadim Suraev
źródło
Jest to gra „wokselowa”, więc tak, trzeba będzie wysłać dużo danych scen.
KaareZ 19.04.16
@KareZ Cóż, prawdopodobnie i tak chcesz wysłać je jako osobne niezależne wiadomości, korzystając z własnych mechanizmów retransmisji. Minecraft zaczął na TCP i był praktycznie niemożliwy do gry przez Internet; przejście na UDP było dobrą okazją dla większości ludzi. Główną ideą jest to, że gdy wysyłasz 20 fragmentów danych wokseli, a pierwszy z nich jest „zagubiony”, nie powinien blokować wyświetlania pozostałych 19 fragmentów, gdy tylko otrzymasz dane; gdy stwierdzisz, że brakuje pierwszego, retransmitujesz. Na TCP wszystkie te 19 są co najmniej zatrzymane, aw najgorszym przypadku retransmitowane.
Luaan 19.04.16
2
@Luaan Minecraft nie przełączył się na UDP dla faktycznej rozgrywki. Nawet najnowsze wersje nadal używają TCP. Nie ma okazji ... :( Jedyną częścią Minecraft, która korzysta z UDP, jest lista serwerów, na której można
pingować
1

Ani UDP, ani TCP (ani żaden inny wariant) nie jest absolutnie lepszy , nawet pod względem szybkości / opóźnienia. Wyboru należy dokonać w zależności od wymagań aplikacji. Aby to zrobić, powinieneś porównać funkcje, które oferuje każdy protokół, zdając sobie sprawę, że więcej funkcji oznacza większe obciążenie. Tak więc, jeśli celem jest zminimalizowanie opóźnień lub maksymalizacja prędkości, powinieneś wybrać protokół z jak najmniejszą liczbą funkcji, ale zachowując podstawowe funkcje potrzebne do spełnienia twoich wymagań.

Porównanie protokołów

Ogólnie rzecz biorąc, UDP (User Datagram Protocol) oferuje najmniejszą liczbę funkcji. Uproszczenie polega na tym, że wysyłasz dane bez żadnego potwierdzenia / potwierdzenia.

Z drugiej strony TCP (Transmission Control Protocol) oferuje najwięcej funkcji potrzebnych do niezawodnej, połączonej komunikacji. Komunikacja TCP wysyła duplikaty lub więcej pakietów i oznacza je informacjami o zamówieniu. Po otrzymaniu w miejscu docelowym należy odesłać potwierdzenie (potwierdzenie) wraz z informacją, które pakiety zostały utracone, aby pierwotny nadawca mógł ponownie wysłać te utracone pakiety. Jeśli dobrze pamiętam, nawet pakiety ACK mogą wymagać potwierdzenia w celu zapewnienia odpowiedniej niezawodności.


Przykład: połączenie konferencyjne Skype

W przypadku połączenia konferencyjnego Skype nie jest ważne, aby wszystkie dane wideo i audio były wysyłane / odbierane w niezawodny sposób. W dzisiejszych czasach UDP ma świetną robotę, minimalizując utratę pakietów. Ważne jest, aby wiedzieć, że w UDP absolutnie nie ma gwarancji, czy transmisja zakończyła się powodzeniem. W przypadku danych audio / wideo podczas połączenia konferencyjnego właściwym wyborem jest UDP, ponieważ bardziej zależy nam na uzyskiwaniu danych w czasie rzeczywistym (czyli najnowszych). Jeśli kilka pakietów zostanie zgubionych tu i tam, nie zakłóci to komunikacji w dramatyczny sposób.

Jednak w trakcie połączenia konferencyjnego ludzie mogą wysyłać wiadomości błyskawiczne (wiadomości błyskawiczne) lub wysyłać pliki. W takich przypadkach niezawodność jest niezbędnym wymogiem, aby zapewnić, że pliki i wiadomości nie zostaną uszkodzone ani utracone. W przypadku wiadomości błyskawicznych może nie być potrzebny stan połączenia zapewniany przez protokół TCP. Może być wystarczający protokół pośredni, taki jak RUDP (Reliable UDP). Jednak w przypadku plików może być konieczne uzyskanie stanu połączenia zapewnianego przez protokół TCP.


Opcje realizacji

Jeśli masz złożoną aplikację lub potrzebujesz zoptymalizować komunikację, warto zacząć od komunikacji UDP. Następnie możesz dodać wszystkie potrzebne funkcje na górze. Zapewni to największą kontrolę nad komunikacją sieciową.

Jeśli masz prostą aplikację, w której optymalizacja nie jest wymagana, rozważ skorzystanie z jednego standardu (UDP lub TCP), aby spełnić Twoje potrzeby. To pozwoli ci przejść do ważniejszych spraw.

Nicholas Miller
źródło
1

Zauważyłem wiele komentarzy, w których ludzie uważają, że pakiety TCP są większe niż pakiety UDP. Nie ufaj mi tylko, przeczytaj dokumentację. Protokół jest następujący: kilka bajtów dla nagłówka Ethernet (2 bajty typu wiadomości, 48 bitów MAC, 6 bajtów) (dla Wi-Fi, nagłówek może się różnić) 20 bajtów dla IP 20 bajtów dla TCP lub UDP x bajtów dla danych x zakres od 0 do około 1500 (patrz MTU) Na koniec suma kontrolna, aby upewnić się, że nie wystąpiło uszkodzenie w tym pakiecie Ethernet.

TCP pozwala na wysyłanie większego pakietu „strumieniowego” o wielkości około 64 KB. Ten „duży” blok jest faktycznie podzielony na wiele mniejszych pakietów Ethernet.

Joust6809
źródło
Próbujesz zasugerować, że nagłówki UDP i TCP mają ten sam rozmiar?
Cameron,