ID:200652
 
Keywords: lag, network, tcp, udp
Skip to TL;DR!!!

There's something I've always wondered.
You see, BYOND only uses TCP for their networking capabilities. Me, being in a game college, I've made networked programs using both TCP and UDP as part of the core curriculum.
Now, the upside to TCP is that you ensure all packets (discrete blocks of data sent over a network) are received undamaged (or you will know if they are damaged) and in the same order they were sent.

Now, some may say that TCP is far superior to UDP, and that makes UDP completely useless for game development. All of this, based on the fact that UDP doesn't give you the features of TCP.
Well, I have a surprise for you, TCP is essentially made from UDP. UDP is a "streaming" protocol that essentially just throws data over a network in the general direction it wants to go. This is bad, because you aren't sure you're getting the exact data that was sent, and you're not sure each packet is received in the order it was sent.

In reality, TCP does that exact same thing (as UDP), it just uses an algorithm on each side of the socket (connection between two computers over a network) to ensure that the data is being transmitted properly.
It does several things, some of them advanced, to check the data by using a header in every packet sent.

TCP was created a long time ago and accepted through an RFC as a "standard" for network transfer. It is quite useful for many applications.
The news is: Like any one-size-fits-all algorithm, it is slower than something made specifically for a given program. It is a really slow protocol for real-time applications, partially because it has to transfer a big amount of extra data in the header and also because of the algorithms it does to maintain correct data transfer.

(Some of said algorithms require sending more/bigger packets. One sizable caveat with networked gaming is how much data you actually transfer. If you transfer less data to achieve the same effect, then your program will automatically be faster. There's one small detail to this, though, that there's sort of a minimum size to a packet that will be sent no matter what -- in which case it is better to pack as much information into one packet as possible.)

Due to the slowness of TCP in real-time, most modern, professional, real-time multiplayer networked games use UDP for networking. They create their own protocol for network transfer that works similar to TCP, but suits their specific application. In this way, they can also optimize their protocol and their game's algorithms to make it run a lot faster than trying to accomplish the same thing with TCP.

One of the problems with network programming, is that, sometimes, you don't get a response from the person on the other end of the socket as soon as you need it. There are ways to change your actual game's algorithm to make this not be a big problem. For example, in a client-server model (which is what BYOND uses), clients send all of their input (mouse, keyboard, etc.) to the server, which then interprets that input and updates their player-character in the server. (The server then has to inform all connected clients of what changed, so everyone connected is up-to-date with what is happening.) Say, for example, a client is pressing the arrow-key to move forward. They sent that arrow-key message to the server, which then moves the player-character and tells all the clients that the player is moving. Now, the next moment, the player that was pressing the arrow key lags a bit, and their data takes time to reach the server. Instead of waiting for the server to tell each client what happens next, the client itself can predict that the player is going to continue moving in whatever direction they were moving, and show that on screen. They can keep doing this until informed otherwise, at which point, they update the position to wherever the player actually is. This looks much smoother and faster to someone playing the game than waiting to receive the next packet before updating. In reality, nothing is faster. It's just a trick to make things seem smoother.

Okay, so the point of that huge essay was my original question: Why doesn't BYOND use UDP? There may be some sort of performance gain if they use it, which will make all games on their system run faster. The only downside (a pretty big one) is that they have to build and maintain their own network protocol. That's not impossible, though. It can be done. Games have done it before, and will continue to do it. The smartest developers know that the way to have fast networking is to use UDP.


TL;DR: UDP is a network protocol that runs faster than TCP, but you have to make and maintain your own protocol for it to be viable. However, it's not impossible to use UDP effectively. So, why doesn't BYOND use UDP?
Using UDP doesn't especially afford benefits on it's own, this isn't really some voodoo magic thing here. What it does, by it's design, is permit a model where-by the application can afford loss of packets and has more flexibility on deciding the consequence of it.

I'm willing to bet, BYOND used TCP classically, because TCP is far less programmer effort to get going with. But once you start on a route of reliable in-order receipt of data, your data-access model starts to mould itself to rely on that concept. You don't ask the question of "maybe I don't always need to receive X", you just sketch the intended execution out between client and server, relying on that transmission.

But I'll go a little further, and answer the follow on question of "Why doesn't BYOND switch to UDP now?"

BYOND (like many currently TCP applications looking to move over to UDP layered replacements) wouldn't inherently benefit much from suddenly developing a protocol on top of UDP and just casually dropping that in at a point where they presently use TCP, because the application through-out assumes reliable in-order transmission from the network layer. To minimise changes to the application, you'd very quickly find your protocol on top of UDP starts to look a lot like a poor man's TCP, with perhaps a few beneficial characteristic changes.

A proper switch to a protocol on top of UDP means more than a port of the network API, it means a proper whole-scale rethink of when and how BYOND's client and server should attempt to use the unreliable nature of UDP, the out-of-order nature of UDP, and when it requires reliability, or in-order receipt. And that's a pervasive change, even in the best designed systems, when the system is so network I/O bound.

As always, I'm welcome to elaborate and answer questions on this, although it's worth noting, I do not have BYOND source code access, I am simply stating my view-point as a software engineer who tends to deal in networking.
Neblim wrote:
I'm curious too. However, I will point out that Byond Flash will be TCP due to Flash socket nature for clients on the web browser level. Web sockets with HTML5 also is TCP.

I know web browsers use TCP as per their protocol. That doesn't necessarily mean anything embedded in a browser page is forced to use TCP. They create their own socket in their application that is different than the one between the browser and the server that the web page is on. (You can have multiple sockets connected to the same machine.)

In other words, if they force you to use TCP in Flash and HTML5 (I'm not convinced they do), then it's a limitation in those platforms, and not a limitation on anything embedded in a web page.
HTML5's websocket API specifies a protocol that uses HTTP UPGRADE of the existing TCP socket, and so is by the standards, going to be a TCP socket.

Flash does provide UDP (or datagram) sockets in AS 3.0. I don't think Neblim implied any inherent limitations on plugins (which flash is) for browsers, beyond the more conventional sandboxing that all browsers do to plugins, and certainly didn't imply UDP limitation inherent in plugins for browsers, just that TCP is the flash plugin defacto. I think you mis-read him.
In response to Stephen001 (#1)
I know it's not "voodoo magic." As I said, I have made working programs using both TCP and UDP, and I have weighed the pros and cons before.

I know it wouldn't be easy to change from TCP to UDP quickly and easily, if you didn't architecture your program for that change.
However, it's not true that you have to use TCP to ensure packets aren't lost. As I said, TCP still uses UDP in the back-end. Packets are still lost, or may show up damaged, just as in UDP. The difference is, you have to implement a packet #, and a checksum yourself for each packet, instead of using TCP's built-in mechanism.
Of course, there's other things to note about this as well, such as the three-way handshake and the other header data. But, all of this is well known. There is an RFC that lists exactly how TCP does everything it does. Using the RFC specification, you could implement the TCP API yourself.
Well, they actually both use IP? But sure. Nor did I say you have to use TCP to ensure reliable delivery, you apparently just chose to read that. RUDP is a fine example of where TCP use is not needed.

However it's not a viable switch for BYOND, is what I'm stating.
Doesn't TCP have some sort of mechanism for slowing down routers if traffic meets some specific circumstance... a throttle to control bandwidth ?
It's more a throttle to control congestion. So if your available bandwidth between two points suddenly drops, TCP will 'back off' the current connection to avoid flooding the link and making matters worse, then slowly increase transmission rates again until a happy medium is found.
The thing of it is, what benefit could there be to switching to UDP?

Reliable delivery of packets is crucial. Would you want your commands going through intermittently or out of sequence?

UDP might be useful for some simple output, like map updates, if said updates were encapsulated in a way that didn't require they be in a certain order. It's best obviously if you have appearance data before you have an obj that uses it, for example. And for file transfers UDP could be fine, since you could just force the packet to contain info about the chunk and fill in chunks nonsequentially.

But by and large, a stateful protocol is not only going to give you way more bang for the buck, it's also more flexible. I have no doubt that a game that does its own low-level networking could find some uses for UDP. But that's also where you're micromanaging all the tiniest details of the game, stuff like object management and player status and whatnot that BYOND already builds in. And our management stuff really wouldn't work well with UDP because sequence matters a lot, so there'd be no point in our implementing it internally.
Is it possible for it to use both TCP and UDP? Each doing what they do best?
In response to Nykuri (#9)
Nykuri wrote:
Is it possible for it to use both TCP and UDP? Each doing what they do best?

That would require more effort than necessary for a pretty low pay-off. Ultimately, using TCP rather than UDP is not as big of a problem as one might infer from looking at this post.