{"id":312,"date":"2022-10-20T01:37:51","date_gmt":"2022-10-20T01:37:51","guid":{"rendered":"https:\/\/merserver.com\/?p=312"},"modified":"2022-10-20T01:37:54","modified_gmt":"2022-10-20T01:37:54","slug":"choosing-tcp-or-udp-a-guide-for-game-developers","status":"publish","type":"post","link":"http:\/\/merserver.com\/index.php\/2022\/10\/20\/choosing-tcp-or-udp-a-guide-for-game-developers\/","title":{"rendered":"Choosing TCP or UDP: a guide for game developers"},"content":{"rendered":"\n<p>As a game developer, you\u2019ll hear lots of myths about network code, especially when it comes to choosing UDP or TCP. You\u2019ll be told that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><em>You can\u2019t build anything fast with TCP<\/em>, dismissing counterexamples.<\/li><li><em>UDP is always faster than TCP<\/em>, ignoring that UDP is deprioritized by traffic-shaping networks.<\/li><li><em>Your game must have the fastest net code<\/em>, pretending that a game\u2019s design or player behavior makes no difference.<\/li><\/ul>\n\n\n\n<p>If you build your game around these myths, then your development progress will slow as you focus on increasingly complex and fragile netcode. Players will become frustrated when the game\u2019s netcode doesn\u2019t mesh with their gameplay expectations. And you\u2019ll be disappointed when your investment in myths doesn\u2019t pay off with your players\u2019 enjoyment.<\/p>\n\n\n\n<p>You need a way to reason about netcode, instead of blindly believing in myths.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"network-dreams\">Network dreams<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/heroiclabs.com\/docs\/expert-tcp-udp\/#network-dreams\"><\/a><\/h2>\n\n\n\n<p>In an ideal world, you wouldn\u2019t have to think about TCP or UDP at all. On a perfect network, every packet sent would be received. There would be no reason to ever confirm receipt of a message. You could&nbsp;<em>trust&nbsp;<\/em>that the network delivered your message anywhere on Earth, in order and in less than about 70ms. Lag and packet loss? Unheard of.<\/p>\n\n\n\n<p>The bad news is that we don\u2019t live in a perfect world with perfect networks. Network conditions vary and protocols serve different needs. Should you choose TCP or UDP? It\u2019s impossible to say. There\u2019s no optimal choice when it comes to your transport layer.<\/p>\n\n\n\n<p>But there\u2019s good news: there\u2019s no optimal choice when it comes to your transport layer. TCP and UDP can satisfy different needs, often within the same game. We don\u2019t have to choose one true protocol. Instead, we can write netcode in concert with game design, minimizing the significance of protocols entirely.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"netcode-and-game-design-are-intertwined\">Netcode and game design are intertwined<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/heroiclabs.com\/docs\/expert-tcp-udp\/#netcode-and-game-design-are-intertwined\"><\/a><\/h2>\n\n\n\n<p>When you think about the relationship between your game\u2019s design and netcode, you\u2019re often thinking in terms of interactivity. What happens when a player makes a decision and acts on that decision? Does the game respond to the player and how does it feel?<\/p>\n\n\n\n<p>Netcode and the network itself are part of that interaction loop. In a first-person shooter, slow messages might give a sluggish or jerky feel to movement. But in a deck-building game, slow messages might heighten the drama and anticipation of the player\u2019s next move.<\/p>\n\n\n\n<p>Of course, few game designs fit neatly into &#8220;fast&#8221; or \u201cslow\u201d interactivity. Most games have a mix of more or less interactive gameplay elements, each with different networking requirements. A deck-builder might have real-time voice chat in addition to turn-based mechanics. A first-person shooter might have discrete, punctuating events, such as matchmaking or consuming an inventory item, alongside a fast, continuous simulation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"some-messages-are-mandatory-and-some-arent\">Some messages are mandatory (and some aren\u2019t)<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/heroiclabs.com\/docs\/expert-tcp-udp\/#some-messages-are-mandatory-and-some-arent\"><\/a><\/h2>\n\n\n\n<p>If your game has more than one mode of interaction, then it doesn\u2019t make sense that your game would have just one way of sending messages over the network. The content of the messages\u2014the type of gameplay that the messages support\u2014can give us a way to reason about how to use the transport layer.<\/p>\n\n\n\n<p>Any one message, depending on its contents, might have more or less impact on your player. If a single frame of voice chat audio is dropped, then it\u2019s unlikely that your player will notice the loss. Some messages, if lost, may be highly aggravating: a lost store purchase confirmation may lead a player to an unwanted repeat purchase. Other messages may fall in-between these extremes: the movement of a projectile might be highly consequential or nearly irrelevant, depending on whether it\u2019s traveling near the player.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/web.archive.org\/web\/20210415231950im_\/https:\/\/heroiclabs.com\/docs\/images\/nakama-tcp-or-udp.png\" alt=\"Gradient of optional and required messages, from voice to purchases\" title=\"Gradient of optional and required messages, from voice to purchases\"\/><\/figure>\n\n\n\n<p>If some messages must<em>&nbsp;<\/em>be received while others are merely nice to have, then the game\u2019s networking code must support a gradient of reliability.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"reliability-is-a-gradient\">Reliability is a gradient<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/heroiclabs.com\/docs\/expert-tcp-udp\/#reliability-is-a-gradient\"><\/a><\/h2>\n\n\n\n<p>Transport layer protocols partly map to the gradient by setting distinct expectations for message delivery.<\/p>\n\n\n\n<p>UDP offers few reliability guarantees. It\u2019s a more trusting protocol that expects that a message will be delivered. If it\u2019s not delivered, the protocol won\u2019t hear or do anything about it. It also doesn\u2019t make any assumptions about when the message is delivered. UDP makes no effort to ensure the order of delivery. The first message you sent may not be the first received. When it comes to reliability, UDP is relaxed.<\/p>\n\n\n\n<p>TCP offers robust reliability guarantees. It goes to some effort to confirm that a connection between the sender and recipient is established, that the recipient is prepared to receive messages, and, after the messages are sent, that they are delivered completely and in order. When it comes to reliability, TCP is a strict micromanager.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/web.archive.org\/web\/20210415231950im_\/https:\/\/heroiclabs.com\/docs\/images\/nakama-tcp-vs-udp.png\" alt=\"UDP vs TCP for reliability and overhead\" title=\"UDP vs TCP for reliability and overhead\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"a-tale-of-four-messages\">A Tale of Four Messages<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/heroiclabs.com\/docs\/expert-tcp-udp\/#a-tale-of-four-messages\"><\/a><\/h3>\n\n\n\n<p>Under good network conditions, it\u2019s actually quite hard to tell UDP and TCP apart in terms of reliability. But if conditions are poor, it\u2019s easier to see how reliability tradeoffs emerge. To illustrate, suppose your game needs to send four messages sequentially (but let\u2019s ignore their contents and importance, for now).<\/p>\n\n\n\n<p>In good conditions, messages arrive intact, promptly, in-order, and just once. In poorer conditions, none of these assumptions hold. How do the different protocols cope?<\/p>\n\n\n\n<p>With UDP, send the four messages, M1, M2, M3, and M4, each one after the other. What happens to each?<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/web.archive.org\/web\/20210415231950im_\/https:\/\/heroiclabs.com\/docs\/images\/nakama-udp.png\" alt=\"Visualization of operation described below\" title=\"Visualization of operation described below\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li>M1 gets lost along the way. It never arrives.<\/li><li>M2 eventually arrives, but the routing is so convoluted, it\u2019s last to arrive.<\/li><li>M3 arrives first!<\/li><li>M4 arrives, but a router along the way spontaneously duplicated the message in transit, so it arrives&nbsp;<em>twice<\/em>, once in second place and once in third.<\/li><\/ul>\n\n\n\n<p>As far as UDP is concerned, this is how it\u2019s supposed to happen. It\u2019s &#8220;best effort&#8221; but at least it\u2019s low overhead. The protocol doesn\u2019t require the receiver to notify the sender of any problems. If anything is to be done about this network hiccup\u2014to make sense of out-of-order delivery, repeated delivery, or the lost message the receiver didn\u2019t even know about\u2014it has to be done at the application layer, in your game.<\/p>\n\n\n\n<p>Let\u2019s rewind things and play this scenario out again over TCP. TCP is a more complex protocol and we\u2019ll have to tell a more complex story. But let\u2019s send those messages again, assuming that we\u2019ve already completed the three-way handshake and we\u2019re in the ESTABLISHED state. What happens to each?<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/web.archive.org\/web\/20210415231950im_\/https:\/\/heroiclabs.com\/docs\/images\/nakama-tcp.png\" alt=\"Visualization of operations described below\" title=\"Visualization of operations described below\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li>M1 gets lost along the way. Eventually resent (more on this later), it arrives last.<\/li><li>M2 eventually arrives, but the routing is so convoluted, it arrives after M3 and M4.<\/li><li>M3 arrives first!<\/li><li>M4 arrives, but a router along the way spontaneously duplicated the message in transit, so it arrives&nbsp;<em>twice<\/em>, in second&nbsp;<em>and&nbsp;<\/em>third place. TCP is clever though and knows to discard the duplicate M4.<\/li><\/ul>\n\n\n\n<p>TCP wants to protect you from this wrong and incomplete order, however. As M2, M3, and M4 arrive, TCP holds those messages until M1 arrives (this is known as&nbsp;<em>head of line blocking<\/em>). While M1 is lost, TCP waits for a while to acknowledge what it has received (delayed ACK) and then waits some more while M1 is resent. Eventually, all four messages are received and TCP hands off the data to your application.<\/p>\n\n\n\n<p>As far as TCP is concerned, this is how it\u2019s supposed to happen. It\u2019s more reliable, but has noticeably more overhead in the form of round-trip exchanges. There are adjustments that can be made to minimize some of the more problematic features (such as turning off delayed ACK), but to get the guarantees of TCP, your application must necessarily submit to these constraints.<\/p>\n\n\n\n<p>Unfortunately, the protocols themselves only represent two points on the reliability gradient. TCP doesn\u2019t have a reduced guarantees mode and UDP doesn\u2019t have an opt-in for more reliability. If our only choices involved choosing TCP or UDP, we\u2019d face a hard decision between the risks of UDP\u2019s best effort and the restrictions of TCP. Luckily, your game has a say in the reliability story, too.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"optionally-reliable\">Optionally reliable<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/heroiclabs.com\/docs\/expert-tcp-udp\/#optionally-reliable\"><\/a><\/h2>\n\n\n\n<p>Your game, as a networked application, can choose how to use the network.<\/p>\n\n\n\n<p>In general, your game is not fixed to a single protocol: you can use UDP when you don\u2019t require the reliability guarantees of TCP and you can switch to TCP when you do. Under good network conditions (low latency and packet loss), this won\u2019t matter much. But if things get shaky, then you\u2019ll avoid some misadventures associated with lost messages.<\/p>\n\n\n\n<p>For points on the gradient between optional and required, there\u2019s a strategy called&nbsp;<em>optionally reliable UDP<\/em>. This is when you build additional guarantees in your application, rather than relying on the protocol. In outline, this is sending UDP packets that require some response from the recipient; the message is re-sent until the expected response is received.<\/p>\n\n\n\n<p>But whether you choose UDP or TCP or optionally reliable UDP comes down to the&nbsp;<em>content<\/em>&nbsp;of your messages and what they mean to your game and players.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"start-with-your-payloads\">Start with your payloads<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/heroiclabs.com\/docs\/expert-tcp-udp\/#start-with-your-payloads\"><\/a><\/h2>\n\n\n\n<p>The content of your messages matters more than the vehicle they travel in. Start by focusing on your payloads, then figure out how to get them there.<\/p>\n\n\n\n<p>Before you start sending messages, make sure you&nbsp;<strong>know what you need to send over the wire<\/strong>&nbsp;(and what you don\u2019t). For example, in an action game, your player\u2019s movements will probably be sent to the server many times per second, while your player\u2019s inventory status only needs to be sent when it changes. Smaller data structures are less likely to pay fragmentation penalties. The fastest packet is the one you never send.<\/p>\n\n\n\n<p><strong>Know your player\u2019s context<\/strong>. Your netcode should reflect when and how your player is interacting with the game. This starts with the player\u2019s physical environment, such as playing on a desktop computer with a high-quality wired connection versus playing from a mobile device on a spotty mobile network. It also includes the game context; the game state may make certain kinds of messages more likely than others.<\/p>\n\n\n\n<p><strong>Know what messages, if lost, would annoy the player<\/strong>&nbsp;(or worse), what they\u2019d never notice, and what\u2019s in between. Each message\u2019s place on the reliability gradient is key. If you know that prediction, interpolation, or other strategies can gracefully hide the occasional lost message, then that gives you more options for sending that message.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"stand-on-shoulders-of-giants\">Stand on shoulders of giants<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/heroiclabs.com\/docs\/expert-tcp-udp\/#stand-on-shoulders-of-giants\"><\/a><\/h2>\n\n\n\n<p>If you\u2019re thinking that this only begins to dig into thinking about net code, then you\u2019re right. As you build out your games netcode, you\u2019ll need to learn more about different aspects of prediction, interpolation, serialization, and beyond.<\/p>\n\n\n\n<p>Read Ruoyu Sun\u2019s&nbsp;<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/ruoyusun.com\/2019\/03\/28\/game-networking-1.html\"><em>Game Networking Demystified<\/em><\/a>, which takes a closer look at game states and client inputs and how they relate to cheating, server authority, and game genre.<\/p>\n\n\n\n<p>Another great read is&nbsp;<em><a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/technology.riotgames.com\/news\/peeking-valorants-netcode\">Peeking into VALORANT&#8217;s Netcode<\/a><\/em>&nbsp;from Riot Games, which goes in-depth on how product design goals can lead to specific decisions in netcode design.<\/p>\n\n\n\n<p>And it always pays to read others\u2019 code. Check out&nbsp;<a href=\"https:\/\/web.archive.org\/web\/20210415231950\/https:\/\/github.com\/minism\/fps-netcode\">Josh Bothun\u2019s open-source implementation of a Quake-style FPS with contemporary netcode techniques<\/a>&nbsp;to see some actual code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As a game developer, you\u2019ll hear lots of myths about network code, especially when it comes to choosing UDP or TCP. You\u2019ll be told that: You can\u2019t build anything fast with TCP, dismissing counterexamples. UDP is always faster than TCP, ignoring that UDP is deprioritized by traffic-shaping networks. Your game must have the fastest net&#8230;<\/p>\n<p class=\"more-link-wrap\"><a href=\"http:\/\/merserver.com\/index.php\/2022\/10\/20\/choosing-tcp-or-udp-a-guide-for-game-developers\/\" class=\"more-link\">Read More<span class=\"screen-reader-text\"> &ldquo;Choosing TCP or UDP: a guide for game developers&rdquo;<\/span> &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-312","post","type-post","status-publish","format-standard","hentry","category-gamedev"],"_links":{"self":[{"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/posts\/312","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/comments?post=312"}],"version-history":[{"count":1,"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/posts\/312\/revisions"}],"predecessor-version":[{"id":314,"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/posts\/312\/revisions\/314"}],"wp:attachment":[{"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/media?parent=312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/categories?post=312"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/merserver.com\/index.php\/wp-json\/wp\/v2\/tags?post=312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}