Examples
This page provides some basic examples on how to use the classes & methods provided by the tcp server lib
Dependencies
libtcp_server
#include "tcp_server.h" /* tcp server classes */
Hint
You can also use the utils and log libs in your project. Check the examples directory for reference usage of these libs.
Create a new instance of the TCP server
tcp_server_t *tcp_server = NULL;
tcp_server = tcp_server_new();
Initialize the TCP server
In order to initialize the TCP server it is required to provide a callback function to process the TCP inbound connection.
The callback function should be the following type:
void (*callback) (void *);
Example callback function:
static void my_connection_callback(void *args)
{
int conn = -1;
int rx_bytes = 0;
char rx_buffer[1500];
conn = *(int *)args;
rx_bytes = read(conn, rx_buffer, 1500);
/* Just loopback */
write(conn, rx_buffer, rx_bytes);
}
Note
The example callback function simply reads the inbound data and writes it back to the connected client. (loopback). The ‘1500’ size of the rx_buffer is the standard MTU size of a standard packet sent over an Ethernet v2.
Initialize the server:
const char *iface = "eth0";
int port = 9010;
int workers = 5;
tcp_server_init(tcp_server, iface, port, my_connection_callback, workers);
The following example initializes the server with 5 workers. The port of the server is 9010 and it is bind on the eth0 interface. The connection callback is the my_connection_callback function shown above.
Run the TCP server
Run the server loop by invocking the tcp_server_run function, passing the tcp_server initialized tcp server object to it.
tcp_server_run(tcp_server);
Beyond this point the server loop takes control of the program execution, no code will be executed until Ctrl+C (SIGINT) interrupt is received.
Destroy the TCP server
Deallocate the server resources with the tcp_server_destroy function
tcp_server_destroy(&tcp_server);
Complete example
/******************************** INCLUDE FILES *******************************/
#include <stdlib.h>
#include <unistd.h>
#include "tcp_server.h" /* tcp server classes */
/******************************* LOCAL FUNCTIONS ******************************/
static void my_connection_callback(void *args)
{
int conn = -1;
int rx_bytes = 0;
char rx_buffer[1500];
conn = *(int *)args;
rx_bytes = read(conn, rx_buffer, 1500);
/* Just loopback */
write(conn, rx_buffer, rx_bytes);
}
/********************************** MAIN **************************************/
int main(int argc, char *argv[])
{
const char *iface = "eth0";
int port = 9010;
int workers = 5;
/* Create new instance of a server */
tcp_server = tcp_server_new();
/* Initialize the server */
tcp_server_init(tcp_server, iface, port, my_connection_callback, workers);
/* Server loop */
tcp_server_run(tcp_server);
/* Destroy server */
tcp_server_destroy(&tcp_server);
return 0;
}
Client - Server Example
The client - server example illustrates the server handling multiple client connections spawned from multiple threads.
Note
The source code of the client-server example is located in the examples/
directory of the project.
In order to run the example code the client and the server side should be started within a seprate shell (terminal) session.
$ cd build/examples
$ ./tcp_server_example
$ cd examples/client
$ python3 client.py
The default console output should look similar to the one shown below:
[08/05/2022 23:05.36] DEBUG (106) main: Using default interface for the TCP server: "lo"
[08/05/2022 23:05.36] WARNING (119) main: Invalid number of workers (0)!
[08/05/2022 23:05.36] INFO (120) main: Applying default number of workers: "5"
[08/05/2022 23:05.36] WARNING (127) main: Invalid port number (0)!. Port range [1024;49151]
[08/05/2022 23:05.36] INFO (131) main: Applying default port number: "9080"
[08/05/2022 23:05.36] INFO (136) main: Server bind interface: lo
[08/05/2022 23:05.36] INFO (137) main: Server port: 9080
[08/05/2022 23:05.36] INFO (138) main: Workers: 5
[08/05/2022 23:05.36] TRACE (80) tcp_server_server_core: TCP Server created [0x55f9f45b5b80]
[08/05/2022 23:05.36] TRACE (60) worker_pool: Worker pool created [0x55f9f45b5c30]
[08/05/2022 23:05.36] INFO (127) worker_pool: Worker 112741 starting ...
[08/05/2022 23:05.36] INFO (127) worker_pool: Worker 112742 starting ...
[08/05/2022 23:05.36] INFO (127) worker_pool: Worker 112743 starting ...
[08/05/2022 23:05.36] INFO (127) worker_pool: Worker 112744 starting ...
[08/05/2022 23:05.36] INFO (127) worker_pool: Worker 112745 starting ...
[08/05/2022 23:05.40] INFO (293) tcp_server_server_core: New connection from: 127.0.0.1:39886
[08/05/2022 23:05.40] INFO (293) tcp_server_server_core: New connection from: 127.0.0.1:39888
RX Buffer
0x000000: 44 61 74 61 20 66 72 6f 6d 20 63 6c 69 65 6e 74 Data from client
0x000010: 20 31 21 1!
[08/05/2022 23:05.40] INFO (157) worker_pool: done
RX Buffer
0x000000: 44 61 74 61 20 66 72 6f 6d 20 63 6c 69 65 6e 74 Data from client
0x000010: 20 30 21 0!
[08/05/2022 23:05.40] INFO (157) worker_pool: done
[08/05/2022 23:05.40] INFO (293) tcp_server_server_core: New connection from: 127.0.0.1:39890
RX Buffer
0x000000: 44 61 74 61 20 66 72 6f 6d 20 63 6c 69 65 6e 74 Data from client
0x000010: 20 32 21 2!
[08/05/2022 23:05.40] INFO (157) worker_pool: done
Server address: 127.0.0.1:9080
Client Threads: 3
Starting client thread: 0.
Starting client thread: 1.
__client_1__ Sending...
Starting client thread: 2.
__client_0__ Sending...
__client_0__ Received:
b'Data from client 0!'
__client_1__ Received:
__client_2__ Sending...
Client thread 0 done
b'Data from client 1!'
__client_2__ Received:
Client thread 1 done
b'Data from client 2!'
Client thread 2 done
Tip
For changing the server/client network routing (ipv4/server iface/port)
use the respective binaries arguments (run ./tcp_server_example --help
and
python3 client.py --help
for more information)