Erlang UDP Server and C++ SFML Client

Introduction

This week I’ve decided to see how well an Erlang UDP Server plays with other languages such as C++. This is to test a current theory of mine which is that Erlang could be used to create a great server for a multiplayer game. 

My theory is based on Erlang’s concurrent nature and its past in telecoms and uptime. The language was designed to handle millions of concurrent users/processes so it should be more than equipped for a small multiplayer game. 

This post isn’t going to be making a functioning game, it’s just going to show how Erlang can talk to C++ and the SFML game development library with a very small amount of effort. Adding game logic and other details is for you to figure out on your own because every game is different. In future I might write a slightly more in depth tutorial about using SFML to create a pong game. Putting this overview into practice on a game of Pong might be a great way to test what you’ve learned (if anything).

To make this small application I’ve chosen to use the in-built Erlang UDP libraries and C++ with SFML. The reason I chose SFML is familiarity and its cross platform nature. This is always a great advantage to me because between work and home I switch between Windows 10 and Xubuntu about 5 times a day, so I like to write code that can run on any of the platforms I use. 

The code for this post can be found here.

Erlang (Server)

Since I am running on Xubuntu installing Erlang was as simple as running:
  
sudo apt-get install erlang

Once you have Erlang installed you can test that it has installed properly by running:
  
erl

This is Erlangs interactive console. Don’t forget your full stops!

Before writing this post I had never used UDP in Erlang and so I follow a tutorial which can be found here. Upon reading more about it I found that it is based on an OTP protocol so I could have made the application with rebar and made it much more concurrent. However, I wanted to create two simple applications to play around with the sending and receiving from two different client languages.

The server code looks something like this:

  -module(server).

  -export([start/1]).

  start(Port) ->
    spawn(fun() -> server(Port) end).

  server(Port) ->
    {ok, Socket} = gen_udp:open(Port, [binary, {active, false}]),
    io:format("Server opened socket: ~p~n", [Socket]),
    loop(Socket).

  loop(Socket) ->
    inet:setopts(Socket, [{active, once}]),
    receive
      {udp, Socket, Host, Port, Bin} ->
        %%Convert incoming binary message to a string
        Message = binary_to_list(Bin),
        io:format("Server received: "),
        io:format(Message),
        io:format("\n"),
        gen_udp:send(Socket, Host, Port, <<"Thanks for the packet, here is my reply packet!">>),
        loop(Socket)
    end.


To run the server open a terminal in the directory where you’ve created the server code and run the commands:
  
erl
c(server).
server:start(54321).


*If you’re on Windows you can open the Erlang application and change the current directory by:
  
cd(“Path to directory”).

C++ SFML (Client)

To get SFML up and running your best bet is to read the docs on the website. Since it is cross-platform there are numerous different ways and possible problems, the documentation has never steered me in the wrong direction.

Now to make the C++ client I have written a small class which connects to the local host on port 12345, takes an input from the user then sends it to the server. The Erlang server will print out the input to the console and respond with “Thanks for the packet, here is my reply packet!”. 

The code looks like this:
    
#include <SFML/Network.hpp>
#include <iostream>
#include <string>

int main() { //Set the port number int Port = 12345; //Set the server address char serverAddress[] = “127.0.0.1”; int serverPort = 54321;

//Create the socket sf::UdpSocket socket;

//Bind the socket socket.bind(Port);

std::cout << “Socket Bound” << std::endl;

//Send a message to the server server std::string message = “Here is my game stuff in a packet”;

std::cout << “Message: “ << message << std::endl;

socket.send(message.c_str(), message.size() + 1, serverAddress, serverPort);

std::cout << “Mesage sent.” << std::endl;

//Recieve a message from the server. char buffer[1024]; std::size_t received = 0; sf::IpAddress sender; unsigned short port; socket.receive(buffer, sizeof(buffer), received, sender, port); std::cout << “Reply: “ << buffer << std::endl;

return 0; }


This should be all of the C++ we need!

To compile it, I used the console commands:
  
  g++ -c main.cpp
  g++ main.o -o client -lsfml-network -lsfml-system
  
  

If you’re using an IDE your compile instructions will probably be different.

It’s all coming together

To test that this has worked let’s open up two terminals. One for the client and one for the server.
First start the server by navigating to the server folder in a terminal and running:
  
  erl
  c(server).
  server:start(54321).
  
  

Secondly start up the client and watch it fire across a message by doing this in the client code folder:
  
  g++ -c main.cpp
  g++ main.o -o client -lsfml-network -lsfml-system
  ./client
  
  
You should now see that the client sends a message to the server, the server displays that message and replies to the client. The client then displays the reply message and ends. The server will stay running, waiting for the next client to connect.

Where to go from here?

To expand the usage there are a couple of small changes you could implement.
The first one would be prompting the user for the message to send on the client.
The second one could be storing the number of connections and returning them to the client.
Lastly you could make the client have a main loop more like a game that fires off to the server constantly polling for data.

Starting the server

Running the client

The view from the server after client execution

Conclusion

This post started as a small experiment for my own mind. I really wanted to know how difficult this was going to be and if there was going to be any weird quirks with the binarys going back and forth between the languages.

It turned out to be super easy and smooth which is a pleasant surprise.
At some point in the future I’m going to implement a proper game with an Erlang backend as a better example.

Thanks for reading and hopefully you’ve learned something (I know I did.).