aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Game-Server

TCP vs UDP für Game-Server: Welches wählen?

Wenn du einen Game-Server schreibst, ist die erste Architekturentscheidung, auf die du früher oder später stößt, das Protokoll der Transportschicht: Welches ist für einen TCP vs UDP Game-Server die richtige Wahl? Die Antwort ist nicht so einfach wie "immer UDP" oder "immer TCP". Beide laufen über dasselbe IP-Netzwerk, transportieren deine Daten aber mit völlig unterschiedlichen Garantien, und diese Garantien bestimmen direkt, wie reaktionsschnell sich dein Spiel anfühlt. In diesem Artikel erkläre ich, was die beiden Protokolle tatsächlich tun, welches Genre zu welchem passt und wie ich in der Praxis entscheide.

Was machen TCP und UDP wirklich?

TCP (Transmission Control Protocol) ist verbindungsorientiert und zuverlässig. Es baut eine Verbindung über einen Drei-Wege-Handshake (SYN, SYN-ACK, ACK) auf und garantiert, dass jedes von dir gesendete Byte in der richtigen Reihenfolge und vollständig am anderen Ende ankommt. Es überträgt verlorene Pakete automatisch erneut, korrigiert die Reihenfolge und drosselt seine eigene Rate, wenn das Netzwerk überlastet ist.

UDP (User Datagram Protocol) ist verbindungslos und folgt dem "Fire-and-Forget"-Prinzip. Es sendet ein Datagramm und kümmert sich nicht um den Rest: Ein Paket kann verloren gehen, in falscher Reihenfolge ankommen oder sogar zweimal auftauchen. Im Gegenzug verursacht es fast keinen Overhead; kein Handshake, kein Warten auf erneute Übertragung.

Kurz gesagt lautet der eigentliche Kompromiss zwischen beiden so:

  • TCP: stets korrekte und geordnete Daten, aber Jitter und das Risiko von Head-of-Line-Blocking.
  • UDP: minimale Latenz und volle Kontrolle, aber du musst die Zuverlässigkeit selbst bauen.

Was die Latenz in Spielen bestimmt: Head-of-Line-Blocking

Um zu verstehen, warum UDP in Spielen so beliebt ist, musst du TCPs heimtückischstes Problem kennen. Da TCP eine geordnete Zustellung garantiert, bleiben beim Verlust eines einzigen Pakets alle danach ankommenden Pakete im Puffer des Betriebssystems liegen; keines davon wird an deine Anwendung weitergegeben, bis das verlorene Paket erneut übertragen wurde und ankommt. Das nennt man Head-of-Line-Blocking.

In einem schnellen Shooter ist das fatal: Ein verlorenes Paket mit der Position des Spielers von vor 40 ms hält auch die aktuellsten Positionspakete auf, obwohl das alte längst veraltet ist. In der Spiellogik zählt jedoch meist der neueste Zustand; den Verlust der Position von vor drei Frames kann man getrost ignorieren. UDP erlaubt dir hier, jedes Datagramm unabhängig zu verarbeiten: Du verwirfst das alte und nutzt sofort das aktuellste.

Welches für welches Genre?

Ein praktischer Entscheidungsrahmen sieht so aus:

  • Echtzeit, schnelles Tempo (FPS, MOBA, Kampfspiele, Rennen, Action-MMO): UDP. Für den konstanten Strom an Positions-/Eingabe-Updates ist niedrige Latenz das Wichtigste, und der Verlust eines einzelnen Pakets ist tolerierbar.
  • Rundenbasiert / langsames Tempo (Kartenspiel, Schach, browserbasierte Strategie, Social/Chat): TCP. Jede Aktion ist kritisch, Millisekunden spielen keine Rolle, und Einfachheit plus garantierte Zustellung gewinnen.
  • Klassische MMORPGs (etwa Metin2 oder Tibia): In der Praxis nutzen die meisten TCP. Inventar, Handel, Chat und Weltzustand erfordern Zuverlässigkeit; auch wenn die Bewegung etwas flüssiger sein könnte, reicht die Konsistenz von TCP für dieses Genre aus und vereinfacht den Servercode erheblich.

Ein wichtiger Punkt: Viele moderne Spiele nutzen beide gleichzeitig. Bewegung und Eingaben fließen über UDP, während Login-Authentifizierung, Käufe, Chat und persistenter Zustand über TCP laufen. Denke nicht "ich muss mich für ein Protokoll entscheiden".

Ein einfacher Vergleich unter Linux

Zu sehen, wie unterschiedlich die beiden Protokolle auf Socket-Ebene eingerichtet werden, macht die Entscheidung greifbar. Unten stehen die Grundgerüste eines TCP-Listeners und eines UDP-Listeners in C++ (POSIX-Sockets). Der Unterschied liegt in SOCK_STREAM gegenüber SOCK_DGRAM und den listen/accept-Schritten bei TCP:

// TCP-Server-Grundgerüst
int fd = socket(AF_INET, SOCK_STREAM, 0);
bind(fd, (sockaddr*)&addr, sizeof(addr));
listen(fd, 128);
int client = accept(fd, nullptr, nullptr); // Verbindung annehmen
recv(client, buf, sizeof(buf), 0);         // zuverlaessiger, geordneter Stream

// UDP-Server-Grundgerüst
int fd = socket(AF_INET, SOCK_DGRAM, 0);
bind(fd, (sockaddr*)&addr, sizeof(addr));
sockaddr_in from; socklen_t len = sizeof(from);
recvfrom(fd, buf, sizeof(buf), 0,
         (sockaddr*)&from, &len);          // verbindungsloses Datagramm

Bei UDP gibt es kein accept und keine persistente Verbindung; jedes Datagramm teilt dir über recvfrom mit, von wem es stammt. Deshalb musst du die "Wer ist welcher Spieler"-Zuordnung, die Sitzungsverwaltung und die Zuverlässigkeit selbst auf der Anwendungsschicht bauen.

Wenn du UDP gewählt hast: die Zuverlässigkeit baust du selbst

UDPs "kostenlose Geschwindigkeit" ist eigentlich nicht kostenlos; du schreibst einen Teil dessen, was TCP dir fertig liefert, von Hand. Typischerweise brauchst du:

  • Sequenznummern: jedem Paket eine aufsteigende Nummer geben, um alte oder doppelte Pakete herauszufiltern.
  • Selektive Zuverlässigkeit: nur das per ACK garantieren, was nicht verloren gehen darf (z. B. "geschossen", "gestorben"-Ereignisse), nicht alles.
  • Überlast- und Ratenkontrolle: die Senderate so abstimmen, dass du das Netzwerk nicht überflutest.

Die gute Nachricht: Du musst das nicht von Grund auf schreiben. Ausgereifte Bibliotheken wie ENet, GameNetworkingSockets (Valve) oder KCP fügen optionale zuverlässige/geordnete Kanäle auf UDP hinzu. Für die meisten Teams ist es der richtige Weg, eine davon statt rohem UDP zu verwenden.

Eine praktische Entscheidungs-Checkliste

  • Ist das Spiel schnelllebig und ist der "neueste Zustand" wertvoller als der alte? → UDP.
  • Ist jede Nachricht kritisch und die Reihenfolge entscheidend, während Millisekunden egal sind? → TCP.
  • Ist die Entwicklungszeit knapp, baust du einen Prototyp? → Beginne mit TCP und verlege die Bewegung bei Bedarf später auf UDP.
  • Ergibt ein Hybrid Sinn? → Ja, die meisten Produktionsspiele machen genau das.

Häufige Fragen

Ist UDP immer schneller als TCP?

In Bezug auf den reinen Durchsatz (Bandbreite) gibt es keinen nennenswerten Unterschied; beide nutzen dasselbe Netzwerk. UDPs Vorteil ist die Konsistenz der Latenz: Da es bei Paketverlust nicht blockiert, vermeidet es Jitter und Head-of-Line-Blocking. Es ist also genauer zu sagen "reaktionsschneller und vorhersehbarer" als "schneller".

Kann ich UDP in einem browserbasierten Spiel verwenden?

Du kannst rohes UDP nicht direkt aus einem Browser öffnen. WebSocket läuft über TCP; für latenzarmen, UDP-ähnlichen Transport verwendest du einen WebRTC-Datenkanal (über UDP, mit optionalen zuverlässigen/ungeordneten Modi). Die meisten Browserspiele funktionieren mit WebSocket einwandfrei, wenn Geschwindigkeit nicht kritisch ist.

Reicht TCP für ein MMORPG wie Metin2?

Ja. Die ursprüngliche Architektur dieser Spiele basiert auf TCP und läuft mit Tausenden von Spielern reibungslos. Der Datenstrom ist nicht so hochfrequent, dass die geordnete Zustellung von TCP zum Problem würde; und für Handel, Inventar und Weltkonsistenz sind die Garantien von TCP genau das, was du willst.

Fazit: Die richtige Antwort hängt vom Rhythmus deines Spiels ab; UDP für schnelles Tempo, TCP für kritische und geordnete Nachrichten und eine Kombination aus beiden in den meisten Produktionsumgebungen. Möchtest du die TCP/UDP-Entscheidung, die Skalierung oder die Netzwerkschicht deiner Server-Architektur gemeinsam festlegen? Nimm Kontakt mit mir auf, und lass uns über die Anforderungen deines Projekts sprechen.

Devamı için