Czy protokół TCP jest wystarczający do gier wieloosobowych w czasie rzeczywistym?


57

Wcześniej połączenia TCP przez połączenie modemowe / ISDN / wolne łącze szerokopasmowe powodowały niestabilne, opóźnione gry, ponieważ pojedynczy upuszczony pakiet spowodował resynchronizację. Oznaczało to, że wielu twórców gier musiało wdrożyć własną warstwę niezawodności na podstawie UDP, lub używali UDP do wiadomości, które można upuszczać lub odbierać poza kolejnością, i używali równoległego połączenia TCP do informacji, które muszą być niezawodne.

Biorąc pod uwagę, że przeciętny użytkownik ma teraz szybsze połączenia sieciowe, czy gra w czasie rzeczywistym, taka jak FPS, może zapewnić dobrą wydajność połączenia TCP?


Odpowiedzi:


36

Powiedziałbym „nie”. Informacje przestrzenne dotyczące obiektów gry muszą być tak szybkie, jak to możliwe, a do tego lepiej używać UDP, ponieważ niezawodność nie jest w 100% krytyczna. Nawet w nowoczesnych połączeniach UDP jest wciąż wystarczająco wolne, aby trzeba było wziąć pod uwagę specjalne interpolacje i tym podobne. Nawet pod względem ilości przesyłanych danych TCP spowodowałby znaczny narzut.

Jednak TCP jest całkowicie akceptowalny w przypadku rzeczy nie będących w czasie rzeczywistym, takich jak negocjacje dla wielu graczy, wiadomości czatu, aktualizacje wyników itp.


7
Sean ma duże pieniądze. Jeśli przez przypadek tworzysz grę w języku C # / .NET (wiesz, że chcesz!), Znalazłem bibliotekę sieci Lidgren ( code.google.com/p/lidgren-library-network ), która jest ładna dobry wybór. Zapewnia nawet uporządkowane, niezawodne przesyłanie komunikatów przez UDP, jeśli jest to potrzebne.
Mike Strobel,

2
Rozsądne jest mieszanie zarówno TCP, jak i UDP; w wyniku sposobu, w jaki TCP wykonuje kontrolę przepływu, może powodować utratę pakietów. (źródło: isoc.org/INET97/proceedings/F3/F3_1.HTM )
Jason Kozak

4
Ważne jest również, aby pamiętać, że w niektórych przypadkach użytkownicy końcowi będą siedzieć za dostawcami usług internetowych, którzy blokują ruch UDP, mają konfiguracje routerów, które zapobiegają ruchowi UDP, lub w inny sposób znajdują się w sytuacji, w której korzystanie z UDP nie jest idealne. W takich przypadkach, jeśli Twoja gra może to obsługiwać, możliwość powrotu do komunikacji TCP jest całkiem przydatna.
Charles Ellis,

Kolejnym + punktem dla UD jest to, że jest naturalnie zorientowany na pakiet, w razie potrzeby musisz go emulować w TCP (boilderplatecode), niestety bardziej nowoczesne protokoły nie są obsługiwane przez Windows (to do bani)
Quonux

11

Ponieważ Flash nie obsługuje UDP, patrząc na gry flash dla wielu graczy, możesz uzyskać całkiem dobre wyobrażenie o tym, co jest możliwe dzięki TCP / IP, a co nie. Zasadniczo możesz tworzyć gry w czasie rzeczywistym, o ile nie polegają one na błyskawicznych czasach reakcji. Kilka przykładów:

http://www.xgenstudios.com/play/stickarena

http://everybodyedits.com/

Jeśli masz opcję korzystania z UDP, naprawdę powinieneś, ale we Flashu niestety nie masz tej opcji.


8

To zależy.

Gry takie jak World of Warcraft używają TCP do komunikacji, ponieważ obchodzisz wiele problemów, używając go. W rezultacie może być wyższy ping, ale w przypadku wielu gier jest to dopuszczalne. Musisz wykonać interpolację przestrzenną, nawet jeśli używasz UDP jako protokołu.


1
To nie tylko ping. Jest powód, dla którego w WoW nie ma kolizji między graczami. Byłoby zbyt trudno zrobić dobrze. WoW może używać TCP, ponieważ to, gdzie stoisz, nie ma większego znaczenia. Celowanie i atakowanie nie zależy od rzeczywistej pozycji potwora lub gracza przeciwnika. Jeśli zależy Ci na tych rzeczach, TCP utrudni grę.
Nuoji

6

Jeśli architektura klienta / serwera jest czysta, warstwa transportowa (prawie) nie ma znaczenia.

TCP ma pewne wady, ale można je łatwo obejść.

Więc tak, TCP i mózg to wszystko czego potrzebujesz.

Dzięki powszechnym ustawieniom sieci (serwery proxy, zapory ogniowe itp.) Dzisiaj UDP jest prawie bezużyteczne dla wszystkich gier oprócz lokalnych (czytaj: LAN).


7
Jeśli głosujesz, zostaw komentarz dlaczego. Używamy TCP i nigdy nie mieliśmy z nim żadnego problemu.
Andreas

3
Nie widzę w tym znaczenia typowych konfiguracji sieci. Zapory ogniowe generalnie zakłócają tylko serwery hostingowe, ale nawet wtedy niezależnie od protokołu, podczas gdy serwery proxy faktycznie zwiększają ryzyko opóźnionego lub upuszczonego pakietu, czyniąc UDP o wiele bardziej użytecznym niż w sieci lokalnej. Wady UDP można w dużej mierze obejść, wykonując samodzielnie kontrole integralności, ale nie można usunąć funkcji z TCP, aby przyspieszyć.
Marcks Thomas

1
Musisz wspomnieć o Nagles . Zawsze zapominam, że to podstawowa przyczyna, dlaczego TCP jest zły (bufory Nagle na kliencie / serwerze, w zasadzie „wstrzymują” je od gry i wprowadzają dodatkowe opóźnienie).
bobobobo

Istnieje kilka powodów, dla których powinieneś używać UDP zamiast TCP, jeśli problemem jest opóźnienie. Jeśli nie przejmujesz się opóźnieniami i / lub jesteś w stanie wykonać wystarczającą prognozę po stronie klienta, wtedy TCP może wystarczyć. W przypadku gier w czasie rzeczywistym. Zapomnij o TCP.
Nuoji,

6

Całkowicie dopuszczalne jest używanie TCP zamiast UDP - jeśli wyłączysz algorytm Nagle .

Gdy wyłączysz Nagle, będziesz mieć większą prędkość UDP i będziesz w stanie stworzyć grę z reakcją na drgania . Rzeczywiście, stworzyłem taką grę za pomocą TCP we Flashu:

http://2dspacemmo.wildbunny.co.uk

Mam nadzieję, że to pomaga!


Nieoperacyjna aplikacja pod twoim linkiem, proszę pana.
Inżynier

Łącze całkowicie obrócone, proszę pana. Dostaję test serwera Apache.
Gustavo Maciel

4

W przypadku gier FPS zawsze używamy UDP. Zwłaszcza jeśli robisz strzelaninę, w której ważne są pingi.


4

To zależy od rodzaju gry.

Niektóre gry, takie jak RTS, grają znacznie lepiej niż TCP i zazwyczaj cały czas używają TCP.

Prawdziwy problem z TCP polega na tym, że jeśli dostaniesz utratę pakietu - nawet niewielką ilość - wtedy połączenie „utknie”, dopóki nie nastąpi retransmisja. System operacyjny nie może dostarczyć do aplikacji danych, które nie są zamówione (narusza to gwarancje TCP, ale także TCP nie wyświetla granic ramki aplikacji). Utrata połączenia oznacza, że ​​później przybywają spóźnione dane. Ale w (np.) Grze FPS nieaktualne dane są bezużyteczne.

Dzięki UDP aplikacja może wybrać, co zrobi z danymi spóźnionymi lub nieczynnymi. Może (i w przypadku gier takich jak FPS zwykle ignoruje stare dane i po prostu pobiera najnowsze). Sporadycznie utracony pakiet wcale nie opóźnia kolejnych pakietów. Jeśli w końcu nadejdzie opóźniony pakiet, może zostać zignorowany przez grę.


Pamiętaj, że twoja implementacja będzie musiała poradzić sobie z aspektem odrzucania opóźnionych pakietów, ponieważ UDP potraktuje to jako odebrany datagram.
Guvante,

3

Nie akceptuj po prostu prostego „tak lub nie, bo tak mówię”, wpisz tutaj odpowiedź, ponieważ możesz otworzyć się na walkę z wieloma problemami z UDP, z którymi tak naprawdę nie musisz się mierzyć.

Żadna z pozostałych odpowiedzi tutaj nie podaje oczywistego sposobu na udowodnienie tego.

Weź kilka prostych faktów

  • Nagłówek IP ma 20 bajtów bez względu na używany protokół.
  • Nagłówki UDP mają 4 bajty
  • Nagłówki TCP mają 20 bajtów

Tak więc za każdym razem, gdy wysyłasz wiadomość o długości 1 bajta w dół linii, faktycznie wysłałeś 25 lub 41 bajtów, w zależności od protokołu, zakładając, że potrzebny jest również nagłówek IP.

źródła:

Moja rada

Weź sytuację, w której potrzebujesz interakcji z serwerem klienta, oszacuj liczbę klientów, a następnie wykonaj obliczenia matematyczne na podstawie danych faktycznie wysłanych między nimi.

Przykład

Powiedzmy, że wysyłam 10 wiadomości po 1 bajcie na aktualizację w mojej grze i aktualizuję około 60 fps, więc muszę wysłać 60 * 10 = 600 bajtów na sekundę rzeczywistych danych wiadomości + odpowiednie nagłówki.

Teraz, w zależności od gry, mógłbym wysłać to wszystko jako pojedynczy komunikat, więc mój narzut z warstwy TCP wynosi zaledwie 40 bajtów (faktycznie koszt ponad UDP wynoszący 20 bajtów na sekundę), brak tego narzutu to potencjalny koszt 600 bajtów ( ponieważ być może będę musiał ponownie wysłać cały strumień wiadomości).

Jeśli jednak niezwykle ważne jest, aby każda wiadomość była wysyłana samodzielnie, natychmiast po przygotowaniu do wysłania, mam 600 wiadomości (także 600 bajtów) + 40 * 600 = 24 k narzut TCP lub ~ 14 k narzut UDP na sekundę + 600 bajtów danych wiadomości.

Ponownie zadajemy pytania, jak ważne są te wiadomości, jak często są one dostępne i czy można je łączyć w jakiś sposób, aby zmniejszyć koszty ogólne?

Opiera się to tylko na kilku jednobajtowych komunikatach, zwykle zrobiłbyś coś zupełnie innego, ale nie wiedząc, że surowe dane są wysyłane, trudno jest udowodnić, czy TCP jest lepiej dopasowany do twojej sytuacji niż UDP.

Czy to zadziała?

Cóż, jeśli masz typową liczbę klatek na sekundę, a pozycja jest ważna (aby uniknąć oszustwa lub niepoprawnych decyzji), musisz wiedzieć, że Twój strumień sieciowy jest niezawodny, ale każdy z 32 graczy przesyła strumieniowo ten 24k + bajt wiadomości w tę iz powrotem (768 KB / s) s + messages) ... to około 10 Mb / s linii szerokopasmowej tylko dla poszczególnych nagłówków na podstawie wysłania co najmniej 1 wiadomości na ramkę od każdego klienta do wszystkich pozostałych klientów za pośrednictwem serwera.

Oczywiście nie będziesz kodować swojego serwera i klienta, aby działał w ten sposób, a rozmiary wiadomości prawdopodobnie będą znacznie większe i prawdopodobnie nieco rzadsze niż 1 bajt na ramkę w większości sytuacji, więc trudno powiedzieć, nie widząc prawdziwego świata przykład „to dane, które muszę wysłać”.

Mój przypadek

W moim przypadku zadzwoniłem, że jest to rozsądny narzut, ale jest to oparte na tym, jak buduję strumienie wiadomości, więc nie mam dużych kosztów ogólnych w porównaniu do niektórych projektów.

TCP działa dobrze i mam skalowalną strukturę serwera i klienta MMO, ale nie muszę przesyłać strumieniowo dużej ilości danych ani ramki, ani wielu małych pakietów, ponieważ mogę grupowo nawiązywać połączenia.

dla innych: TCP po prostu tego nie zrobi i mogą korzystać tylko z UDP, ale muszą zaakceptować, że nie da im to pewności, co otrzymają (gwarancja zamówienia / przyjazdu).

Inne uwagi

Wiele źle zakodowanych silników gier obsługuje wszystko w głównym wątku procesora, więc procesorowi często daje się bardzo mało czasu na obsługę kodu sieciowego, przyzwoita implementacja zarówno serw, jak i klienta byłaby całkowicie asynchroniczna i prawdopodobnie push i ciągnąć wiadomości partiami.

Istnieje kilka dobrych bibliotek sieciowych, ale jak widać tutaj, wielu wydaje się mieć opinię, że UDP jest „po prostu lepszy”, najpierw należy uwzględnić własne potrzeby, a może nie być tak, i znaleźć bibliotekę, która nie czynnik w ten sposób, w jaki robisz, może prowadzić do źle zakodowanej konfiguracji TCP w porównaniu z wariantem UDP w tej samej bibliotece (mówię tylko, że to widziałem, a testy obciążenia to udowodniły).

Zbuduj najpierw bazę techniczną danych, które chcesz wysłać, i przetestuj, a następnie wykonaj matematykę, aby ją skalować, w najgorszym przypadku przetestuj ją, wdrażając w chmurze i 50 komputerów uruchomi klienta testowego, aby sprawdzić, czy da sobie radę twój limit 32 graczy na grę (lub jakiekolwiek ograniczenia, jakie możesz mieć).


2

Nie sądzę ... Gry, w których przesyłanie danych jest bardzo częste (po poruszeniu myszą lub naciśnięciu klawisza), powinny korzystać z UDP. Opóźnia się nawet w sieci LAN, jeśli używany jest protokół TCP.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.