[SDL2 Part – 12 ] Multiplayer


A huge aspect of game programming is multiplayer. A huge share of all the popular video games today support internet in sme ways. But this introduces several new challanges. Both in the communciation over internet itself but also in what data to send, how to react to data and how to make everything synchronized. This is going to be a sub series in itself starting off with how to do the actual communication.


When you’re sending something over the Internet, it’ll get split into quite small packages. Each of these packages are usually a few kilobytes or smaller. There are actually several types of packages which get wrapped in each other. I won’t get into the details of this, but what we need to know is that there are several types of packets and they get wrapped in each other.

One of the basic packet types is the IP ( Internet Protocol ) packet. You can look at this as the package that leaves our computer and is sent out on the Internet. Every package that is sent across the Internet is of this type.

IP package

We won’t go into the details of each of these fields, the image is there just to show you how it looks. I might go into the details on a later point in time, but that is a big topic and we don’t really need to know all of that in order to do multiplayer.

The package is then sent out on the Internet and will eventually find its way to its destination PC. This is similar to sending a letter. You put the letter inside an envelope and write the destination address on it. Then the mail carrier will take care of the rest.

Actually, that isn’t entirely true because there is another step before the package leaves your computer; we need a protocol.


Above we saw an example of in IP package.

So now that we know about packages, the next topic is protocol. A protocol is basically a set of rules about how the two parts should communicate. Most important to us, these rules dictate how to detect package loss and how to deal with them.

Why do we need protocols?

Most of the times when you send something, everything goes fine and the recipient gets the data packages he need. But things can go wrong. Let’s take an example.

Say we have sent our letter to someone. But on it’s way, the letter gets lost. But how can we know? The mail carrier doesn’t know that the letter is lost. The recipient doesn’t know you’ve sent the letter and you yourself is assuming the letter arrived at its destination without any issues.

The exact same thing could happen on the Internet ; packages can get lost, and none will know. So how can the problem be avoided? This is where protocols come in!

There are two protocols, we’ll cover, TCP and UDP. This time, I’ll only cover UDP. I’ll cover the other one, TCP, in a later post.


The most basic of the protocols we’ll look at is UDP ( User Datagram Protocol. ) Actually, UDP is so basic, there is no rules about how to deal with package loss. You have to handle that yourself.

Another issue is that there is no guarantee that the packages will be received in order. So you could get packages 1,2,3 as 3,2,1 or 3,1,2 or 2,3,1 etc.. And that’s if you do get all packages. Needless to say, using UDP can cause lots of problems. But its’ simple so we’ll start with it.

UDP is generally used for performance or simplicity reasons :

  • Video streaming
    • If a package is lost, this is just a tiny piece of the stream data and you might not even notive it
  • In cases where you just want to send a state to the server
    • Like using ping where you just get an echo back
    • If you don’t get a message back, you can retry again and again, or report an error
  • Games
    • For reducing lag
    • This means they have their own way of dealing with package loss

Addressing on the internet

On the Internet, there are two units used for addressing, the IP address and the port number. We need both of these to communicate over the Internet.

IP adress

The IP address is used to address computer. Every unit on the Internet has an IP address that refers to that unit. You can look at it as the address of a house. So when you send a letter to someone in a house, you write the address to that house. When you send a packet to a computer, you send a packet to that IP address.

Port numbers

Port numbers are used to distinguish between connections. Each connection has a separate port number tied to it. If we didn’t have port numbers, all data would go into a large buffer and you’d have no idea which of these datas where yours.

So if an IP adress refers to a house, a port could be looked at as a name.

When you set up a connection, you need both of these an IP address and a port number. Actually you need two of both since the receiver needs to know who sent the package so that it needs to know who to reply to. So all in all, we need two IPs ( out IP and destination IP ) and two port numbers ( our port numbers, destination port numbers. )

So basically, you neeed :

  • Your own IP adress and port number
  • The recipients IP address and port number

Setting up the connection

Actually, UDP is not really a connection, it’s just two parts sending data back and fort. But both parts still needs to know both IP and port number of each other. And it is common and more practical to think about it as an actual connection.

There are two roles in a UDP “connection”.

  • A client
    • Tries to connect to a server
  • A server
    • Waits for a connection from a client

So the procedure for a “connection” will be something like this

  • Server with ip waits for connection, listening to port 123
  • Client sends a packet to, port number 123
  • Server stores IP and port number for client
  • Server and client now knows both port number and IP of each other
  • Now the server and client can now send data back and forth


The final part we need to cover about connections are sockets. A socket is a combination of IP address and ports that is unique on every PC for every connection. It consists of the following :

  • IP and port of the client side of the connection
  • IP and port of our the remote part of the connection
    • This part is mostly used for TCP connections, we won’t use it
  • Type of connection ( UDP, TCP, etc… )

We’ll be using sockets as a unit to keep track of a connection. You can look at scokets to the sockets you plug your electric devices to. Following that analogy, the wire would be the connection ( network cable ). So, in essence, it’s what connects your application to the Internet.

I realize this all might be a lot of information and hard to wrap your hand around it all, but it’ll get clearer when we put it to use.


Now that we know a tiny bit about UDP connections, let’s try to set up one ourselves. For that purpose, we need the SDL_net library. It is capable of setting up and maintaining both UDP and TCP connections. Since UDP connections are way simpler, we’ll only cover that for now.

Networking is, just like text rendering and .png loading, a separate part of SDL called SDL_net. We install it the exact same way as before :


Installing SDL2_net is done exactly like SDL2_image. Just replace SDL2_image with SDL2_net

Here’s the short version :


For Linux you can use need to install -lSDL2_net or -libSDL2_net or -SDL2_net ( the actual name might be different in different distributions. )

The linker flag is -lSDL2_net

The process is more or less identical to that of setting up SDL2_image.

If you can’t find SDL2_net in any repositories and it’s not installed by default, you might have to compile it yourself. For more information, see my blog post about setting up SDL2.


Similar to setting up SDL2 base.

The difference is that you have to download the development files for SDL2_net

And similarly add SDL2_net.lib to library includes and add SDL2_net.lib to the library flags ( where you previously added SDL2_image.lib )

And with that, it should work.


See the first part of my tutorial. Just install SDL2_net instead of SDL2

Using SDL_net to set up a connection

Setting up a connection with SDL_net is a bit more complicated than what we’ve previously seen. This is because there are a few steps, the code will be very C ( not C++ ) and there are some buffers ( raw arrays ) we need to keep track off.

We’ll be cutting out all GUI because we simply don’t need it. It will make our code shorter and it’ll be easier to display the results.

Structures of SDL_net

SDL_net contains two parts we need for out UDP connection. Let’s start with the simplest, IPAddress.


A simple struct with the following fields :

  • uint_32_t hostIP v4 address
  • uint16_t host – protocol port

It is used for keeping IP and port number together. Some functins takes this as one of the parameters.


A pointer to a data type that holds to a pointer. Since it a pointer, it can be NULL, in which case there is no connection and we can’t send data back and forth.


Our data packet. Contains the data we are sending back and forth along with some other information.

  • int channel
    • The src/dst channel of the packet
    • We won’t be using this
  • Uint8 *data
    • The packet data we’re sending
    • Can be of any length
  • int len
    • The length of the packet data
    • Used to find the end of the data in the data pointer
  • int maxlen
    • The max size of the data buffer
    • Always as large or larger than len
    • Only used for data package creation on the senders side
  • int status
    • Packet status after sending
    • Number of data sent
    • -1 on failure
  • IPaddress address
    • the source/dest address of apacket
    • For received packages this is the IP / port of the remote part.
    • For sent packages this is the IP / port to send to.

The various fields of a UDP packet is set with various function used for sending and receiving data. It might seem confusing right now, but it’ll get clearer once we get into the actual code.

Functions of SDL_net


This function is just like SDL_Init and TTF_Init ; it initializes the SDL_net


This function is used for creating a socket which we will use later to send data.

Parameters :

  • Uint16 port – the port we want to use. If you use 0, SDL_Net will assign a port for you.

Return value :

A valid UDPsocket, NULL on error. Remember that UDPSocket is a pointer.

As we saw earlier, UDP isn’t actually a connection. All we are doing is sending data back and forth. And all we need to do that is a socket. Now that we’ve opened this socket, we can start dealing with packages.


As stated before, we need an IP address and port number in order to send data. The problem is that there are several ways to represent IP addresses and port numbers. The difference between them is the order in which the they are converted to binary. These orders are refereed to as little endian and big endian I won’t dive more into this, but you can read about it here.

The issue is that different system use different endian. So we need a uniform way of setting the IP address and port number. This is where SDLNet_ResolveHost comes in. What it does, is that it sets the name values of an IPAdress for us so we don’t have to think about endians at all.

Parameters :

  • IPaddress* address – a pointer to an IPAdress. Needs to be allocated / created in advance. ( In our case, we’ll use a variable and not a pointer so we don’t have to worry about this. )
  • const char* hostIP address to send to ( xxx.xxx.xxx.xxx )
  • Uint16 port – the port number to send to

Return value :

0 on success, otherwise -1. In this case, address.host will be INNADDR_NONE. This can happen if the address is invalid or leads to nowhere


Allocates a UDP_Packet and returns a pointer to it.

Parameters :

  • int size – size of the packet in bytes. 0 is invalid.

Return value :

A valid pointer to UDPpacket, NULL on error ( such as out of memory )

The size of the packet determines how much data we get every time. It’ll never be more than this size, but it can be less. You can also expect that some packages gets mfSerged or split up into different segments. This is something we’ll need to handle.

After allocation space for a packet, we can finally fill that packet up with something. Which is kinda the point of this ordeal.


Sends a UDPpacket

Parameters :

  • UDPsocket sock – Our socket to send data from ( the one we created with SDLNet_UDP_Open )
  • int channel – We’ll completely ignore this parameter and just set it to -1 ( all channels )
  • UDPpacket* packet – the data we want to send ( finally! )

Return value :

The number of destinations the packet was sent to. In our case, this will be 1. But it could be more. Because of this 0 is returned on errors. Anything higher than 0 means partial success ( since we were able to send to at least one destination. )

In our case, the function should always return 1 but I find it better to just check for 0.


Now that we know how to send data, we also need to know how to recieve them.

Parameters :

  • UDPsocket sock – Our socket to receive data from ( the one we created with SDLNet_UDP_Open> )
  • UDPpacket* packet – the data we received

Return value :

The int value 1 when a packet is received, 0 when no packets where received, and -1 on errors.


To make it simpler to use SDL_Net, I’ve made a helper class that takes care of everything. You’ll find an example at how to use it below.


To compile it on Linux or Mac. Simply run :

clang++ UDPExample.cpp -std=c++11 -lSDL2_net -o UDPTest

Starting the example

To use the example, you need two instance of the application. So start up two instances of it.

You’ll be asked to enter local IP. This is the IP of the computer you are sitting on. You can use which simply means “this computer”. You can do this in both instances. You’ll also be asked to enter a local port and remote port. These needs to be opposite on the two instances ; the local port of the first one, needs to be the remote port of the other. This is because we need to know where to send it to and where to listen for data on.

Instance 1

Instance 2

( notice the difference in local and remote port on the two instances. )

Using the example

After inserting IP and port data, you’ll be presented with a simple menu :

Nothing will happen before you do one of the three options. And if your message doesn’t show up on the other instance, make sure you’ve entered ‘2’

And now you should be able to set up connections. Feel free to use the UDPConnection struct as you like.

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com