Client for accept pool testing: connects repeatedly to stress the server.
Usage: ./ex_accept_pool_client -s HOST -p PORT -n 500 -t 8 ./ex_accept_pool_client -s HOST -p PORT -n 500 -t 8 -e (echo mode)
Default mode: connect + close (measures pure accept throughput). With -e: connect, send message, wait for echo, close.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#define NETMSG_DATA 1
pthread_mutex_lock(&state->
lock);
pthread_mutex_unlock(&state->
lock);
return NULL;
}
pthread_mutex_lock(&state->
lock);
pthread_mutex_unlock(&state->
lock);
return NULL;
}
pthread_mutex_lock(&state->
lock);
pthread_mutex_unlock(&state->
lock);
return NULL;
}
if (msg) {
if (packed) {
}
}
if (response) {
pthread_mutex_lock(&state->
lock);
pthread_mutex_unlock(&state->
lock);
} else {
pthread_mutex_lock(&state->
lock);
pthread_mutex_unlock(&state->
lock);
}
return NULL;
}
static void usage(
void) {
fprintf(stderr,
"Usage: ex_accept_pool_client [options]\n"
" -s HOST server address (required)\n"
" -p PORT server port (required)\n"
" -n COUNT number of connections (default: 500)\n"
" -t THREADS concurrent client threads (default: 8)\n"
" -e echo mode: send+recv messages (default: connect+close)\n"
" -V LEVEL log level (default: LOG_NOTICE)\n"
" -h show this help\n");
}
int main(
int argc,
char** argv) {
char* host = NULL;
int total = 500;
int nb_threads = 8;
int opt;
while ((opt = getopt(argc, argv, "hes:p:n:t:V:")) != -1) {
switch (opt) {
case 's':
host = strdup(optarg);
break;
case 'p':
break;
case 'n':
total = atoi(optarg);
break;
case 't':
nb_threads = atoi(optarg);
break;
case 'e':
break;
case 'V':
if (!strcmp(optarg, "LOG_DEBUG"))
else if (!strcmp(optarg, "LOG_INFO"))
else if (!strcmp(optarg, "LOG_NOTICE"))
else if (!strcmp(optarg, "LOG_ERR"))
break;
case 'h':
default:
exit(1);
}
}
fprintf(stderr, "Error: -s HOST and -p PORT are required\n");
exit(1);
}
#ifdef __linux__
signal(SIGPIPE, SIG_IGN);
#endif
pthread_mutex_init(&state.
lock, NULL);
exit(1);
}
n_log(
LOG_NOTICE,
"=== Starting %d connections to %s:%s (%d threads, %s mode) ===",
total, host,
port, nb_threads,
struct timespec t_start, t_end;
clock_gettime(CLOCK_MONOTONIC, &t_start);
for (int i = 0; i < total; i++) {
if ((i + 1) % 100 == 0) {
}
}
clock_gettime(CLOCK_MONOTONIC, &t_end);
double elapsed = (double)(t_end.tv_sec - t_start.tv_sec) +
(double)(t_end.tv_nsec - t_start.tv_nsec) / 1e9;
elapsed, (double)total / elapsed);
pthread_mutex_destroy(&state.
lock);
netw_unload();
return 0;
}
static int client_echo_mode
#define NETMSG_DATA
type of data message
size_t success_count
atomic counter of successful connections
pthread_mutex_t lock
mutex for counters
static void * client_worker_fast(void *ptr)
Fast mode: connect and immediately close (measures pure accept throughput)
static void * client_worker_echo(void *ptr)
Echo mode: connect, send a message, receive echo, close.
size_t fail_count
atomic counter of failed connections
shared state for client threads
static NETWORK_POOL * pool
NETWORK * netw
Network for server mode, accepting incomming.
#define FreeNoLog(__ptr)
Free Handler without log.
#define __n_assert(__ptr, __ret)
macro to assert things
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
#define LOG_NOTICE
normal but significant condition
#define LOG_INFO
informational
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
A box including a string and his lenght.
N_STR * make_str_from_msg(NETW_MSG *msg)
Make a single string of the message.
int add_nstrptr_to_msg(NETW_MSG *msg, N_STR *str)
Add a string to the string list in the message.
int create_msg(NETW_MSG **msg)
Create a NETW_MSG *object.
int add_int_to_msg(NETW_MSG *msg, int value)
Add an int to the int list int the message.
int delete_msg(NETW_MSG **msg)
Delete a NETW_MSG *object.
network message, array of char and int
int netw_add_msg(NETWORK *netw, N_STR *msg)
Add a message to send in aimed NETWORK.
int netw_start_thr_engine(NETWORK *netw)
Start the NETWORK netw Threaded Engine.
#define NETWORK_IPALL
Flag for auto detection by OS of ip version to use.
int netw_close(NETWORK **netw)
Closing a specified Network, destroy queues, free the structure.
N_STR * netw_wait_msg(NETWORK *netw, unsigned int refresh, size_t timeout)
Wait a message from aimed NETWORK.
int netw_connect(NETWORK **netw, char *host, char *port, int ip_version)
Use this to connect a NETWORK to any listening one, unrestricted send/recv lists.
#define NORMAL_PROC
processing mode for added func, synced start, can be queued
THREAD_POOL * new_thread_pool(size_t nbmaxthr, size_t nb_max_waiting)
Create a new pool of nbmaxthr threads.
int add_threaded_process(THREAD_POOL *thread_pool, void *(*func_ptr)(void *param), void *param, int mode)
add a function and params to a thread pool
int wait_for_threaded_pool(THREAD_POOL *thread_pool)
Wait for the thread pool to become idle (no active threads, empty waiting list), blocking without pol...
int destroy_threaded_pool(THREAD_POOL **pool, unsigned int delay)
delete a thread_pool, exit the threads and free the structs
Structure of a thread pool.
Common headers and low-level functions & define.
Network messages , serialization tools.