How to Set Up a SFML Game Server to a Linux Server

When I first started tinkering with SFML to make my own little client server game, I thought getting the server running on my own machine was the hard part. Oh, sweet summer child. It turns out that deploying it to another Linux box without SFML installed is a rite of passage for any budding game developer.

Today, I’m going to walk you through how I built my SFML game server, the errors I ran into, and how I fixed them so you can get your own server running without tearing your hair out.

The First Working Server Code

I began with the simplest TCP server possible using SFML’s networking module. Here’s what it looked like:

// server.cpp
#include <SFML/Network.hpp>
#include <iostream>

int main() {
sf::TcpListener listener;

// Bind the listener to a port
if (listener.listen(53000) != sf::Socket::Done) {
std::cerr << "Error: Could not bind to port 53000.\n";
return 1;
}
std::cout << "Server listening on port 53000...\n";

sf::TcpSocket client;
if (listener.accept(client) != sf::Socket::Done) {
std::cerr << "Error: Could not accept client connection.\n";
return 1;
}

std::cout << "Client connected!\n";

sf::Packet packet;
std::string message = "Hello from server!";
packet << message;
client.send(packet);

return 0;
}

I compiled it locally with:

g++ server.cpp -o ServerLinux -std=c++11 -lsfml-network -lsfml-system

On my dev machine, it ran perfectly. Victory dance, right?
Not so fast.

The Error That Stopped Me

The moment I copied the binary to a fresh Linux server and tried to run it, I was greeted with this:

error while loading shared libraries: libsfml-network.so.2: cannot open shared object file: No such file or directory

So I tried static linking instead, thinking “Fine, I’ll just bake everything into the executable.” That gave me:

GLIBC_2.15 not found
GLIBC_2.17 not found

What Was Actually Happening

The code itself was innocent. The real villain was how Linux handles libraries.

  • Dynamic Linking Problem
    My binary depended on SFML’s shared libraries (.so files). By default, Linux does not search the binary’s own folder for .so files it looks in system library paths like /usr/lib. No .so there Boom: error.
  • Static Linking Problem
    You can statically link SFML, but you can’t fully statically link glibc in a portable way. glibc is deeply tied to the Linux kernel and system calls. If the server you built on has a newer glibc than the target system, you get the dreaded GLIBC_2.xx not found.

Key takeaway:
If the target system doesn’t have SFML, you either:

  1. Ship the .so files with your binary and tell it where to find them (using rpath or LD_LIBRARY_PATH), or
  2. Build on an older Linux with a compatible glibc and statically link everything except glibc.

Making the Server More Practical

Once I figured out deployment, I decided to upgrade the server. I wanted:

  • Support for multiple clients
  • Simple message handling
  • Logging for debugging

Here’s the new version:

// multi_server.cpp
#include <SFML/Network.hpp>
#include <iostream>
#include <fstream>
#include <vector>

int main() {
std::ofstream logFile("server.log", std::ios::app);
sf::TcpListener listener;
listener.listen(53000);
logFile << "Server started on port 53000\n";

std::vector<sf::TcpSocket*> clients;
sf::SocketSelector selector;
selector.add(listener);

while (true) {
if (selector.wait()) {
// New connection
if (selector.isReady(listener)) {
auto* client = new sf::TcpSocket;
if (listener.accept(*client) == sf::Socket::Done) {
logFile << "New client connected from " << client->getRemoteAddress() << "\n";
clients.push_back(client);
selector.add(*client);
} else {
delete client;
}
} else {
// Existing client sent data
for (auto it = clients.begin(); it != clients.end(); ) {
sf::TcpSocket& client = **it;
if (selector.isReady(client)) {
sf::Packet packet;
if (client.receive(packet) == sf::Socket::Done) {
std::string msg;
packet >> msg;
logFile << "Received: " << msg << "\n";
} else {
logFile << "Client disconnected\n";
selector.remove(client);
delete *it;
it = clients.erase(it);
continue;
}
}
++it;
}
}
}
}
}

Compiling for Deployment

To make deployment painless, I used rpath so the binary looks for .so files in its own directory:

g++ multi_server.cpp -o ServerLinux -std=c++11 \
-lsfml-network -lsfml-system \
-Wl,-rpath,'$ORIGIN'

Then I copied:

ServerLinux
libsfml-network.so.2
libsfml-system.so.2

into the same folder on the target server. That’s it no system-wide SFML install required.

Final Thought

Deploying SFML projects to a Linux server without SFML pre-installed isn’t impossible, but it does force you to understand how Linux deals with libraries. The moment I stopped fighting glibc and started shipping the .so files alongside my binary, everything clicked. Now my little SFML server runs on anything I throw it at, and I can spend more time building the game instead of wrestling with deployment.

Related blog posts