
The goal for a server is to send a message when a client is connected.
The server should handle multiple users concurrently for that we will use a thread for each client.
We start by defining some constant for the client and the buffer
#define MAX_CLIENTS 10
#define BUFFER_SIZE 512
#define SERVER_PORT 8654
For the client we will need to store the socket, the thread and the id forr that we use a struct:
typedef struct {
NET_StreamSocket* socket;
SDL_Thread* thread;
int id;
} Client;
SDL_Init(SDL_INIT_VIDEO);
NET_Init();
We resolve the hostname for running something localhost, we then wait at most 2 seconds for the adress to be resolved.
NET_Address* ip = NET_ResolveHostname("127.0.0.1");
NET_WaitUntilResolved(ip, 2000);
if (!ip) {
printf("ResolveHost error: %s\n", SDL_GetError());
return 1;
}
NET_Server* server = NET_CreateServer(ip, SERVER_PORT);
if (!server) {
printf("TCP_Open error: %s\n", SDL_GetError());
return 1;
}
We create the tcp socket and wait for the acceptation of the client
NET_StreamSocket *stream;
bool new_client = NET_AcceptClient(server, &stream);
if (!new_client || !stream) {
SDL_Delay(10);
continue;
}
We need to wait for the connection we set a timeout of 2 seconds. If the client failed to connect we destroy the socket
if (!NET_WaitUntilConnected(stream, 2000)) {
printf("Client failed to connect properly.\n");
NET_DestroyStreamSocket(stream);
continue;
}
If the max number f client is reached we destroy the socket the server is full.
if (client_count >= MAX_CLIENTS) {
printf("Max clients reached. Connection refused.\n");
NET_DestroyStreamSocket(stream);
continue;
}
We can fill the arrays of client with the informations we have and start the thread for the client:
clients[client_count].socket = stream;
clients[client_count].id = client_count;
clients[client_count].thread = SDL_CreateThread(client_thread_func, "ClientThread", &clients[client_count]);
After that we check if the thread is correctly created:
if (!clients[client_count].thread) {
printf("Failed to create thread for client %d\n", client_count);
NET_DestroyStreamSocket(stream);
} else {
printf("[Client %d] Connected\n", client_count);
client_count++;
}
Inside the thread the server wait for a message with NET_ReadFromStreamSocket send back a message with NET_WriteToStreamSocket.
int client_thread_func(void* data) {
Client* client = (Client*)data;
char buffer[BUFFER_SIZE];
printf("[Client %d] Thread started\n", client->id);
while (true) {
if(!client->socket) break;
bool ready = NET_WaitUntilInputAvailable((void**)&client->socket, 1, 5000);
if (!ready) {
continue;
}
int len = NET_ReadFromStreamSocket(client->socket, buffer, BUFFER_SIZE - 1);
if (len <= 0) {
printf("[Client %d] Disconnected\n", client->id);
break;
}
const char* message = "Hello from server!";
len = (int)strlen(message);
printf("[Client %d] Received: %s\n", client->id, buffer);
// Echo back to client
NET_WriteToStreamSocket(client->socket, message, len);
NET_WaitUntilStreamSocketDrained(client->socket, 2000);
}
NET_DestroyStreamSocket(client->socket);
return 0;
}
After exiting the loop you need to do some clean up.
NET_DestroyServer(server);
NET_Quit();
SDL_Quit();
return 0;
The client send a message to the server after connection.
#define SERVER_PORT 8654
#define BUFFER_SIZE 512
SDL_Init(SDL_INIT_VIDEO);
NET_Init();
NET_Address* server_addr = NET_ResolveHostname("127.0.0.1");
NET_WaitUntilResolved(server_addr, 2000);
if (!server_addr) {
printf("Failed to resolve server address.\n");
return 1;
}
We cerate the tcp socket and wait for the client to be connected to the server
NET_StreamSocket* socket = NET_CreateClient(server_addr, SERVER_PORT);
if (!socket) {
printf("Failed to create stream socket.\n");
return 1;
}
if (!NET_WaitUntilConnected(socket, 2000)) {
printf("Connection timed out.\n");
NET_DestroyStreamSocket(socket);
return 1;
}
We can send a message to the server and wait 2 seconds until everything is sent.
const char* message = "Hello from client!";
int len = (int)strlen(message);
printf("Sending: %s\n", message);
NET_WriteToStreamSocket(socket, message, len);
NET_WaitUntilStreamSocketDrained(socket, 2000);
We wait for the client to be available again.
bool ready = NET_WaitUntilInputAvailable((void**)&socket, 1, 5000);
while (!ready) {
continue;
}
We read a message from the server and display the message.
char buffer[BUFFER_SIZE];
int received = NET_ReadFromStreamSocket(socket, buffer, BUFFER_SIZE - 1);
if (received > 0) {
buffer[received] = '\0';
printf("Received echo: %s\n", buffer);
} else {
printf("No response or connection closed.\n");
}
After exiting the loop we need to destroy the tcp socket.
NET_DestroyStreamSocket(socket);
NET_Quit();
SDL_Quit();
Need another OS ? => Windows, Mac, Linux