IRSOL
C++ code implementing socket server for interacting with Baumer camera.
main.cpp File Reference

Demonstrates a sample client-server interaction using sockets. More...

#include "irsol/irsol.hpp"
#include "sockpp/tcp_acceptor.h"
#include "sockpp/tcp_connector.h"
#include <chrono>
#include <random>
#include <string>
#include <thread>
#include <vector>

Go to the source code of this file.

Classes

struct  Params
 Command-line parameters for the program. More...
 

Macros

#define PROGRAM_NAME   "client-server-interaction-demo"
 

Functions

const std::string getProgramName ()
 
std::thread runServerThread (irsol::server::App &app)
 Demonstrates handler creation, registration, and dispatch.
 
void clientThreadBody (std::string clientName, irsol::types::port_t port, std::vector< std::string > commands)
 The function executed by each client thread.
 
std::thread runClientThread (const std::string &clientName, irsol::types::port_t port, const std::vector< std::string > commands)
 TCP client that connects to the server and sends commands at random intervals.
 
Params getParams (int argc, char **argv)
 Parses command-line arguments using args library.
 
void runDemo (uint32_t numClients)
 
int main (int argc, char **argv)
 Main entry point for the handler demo application.
 

Detailed Description

Demonstrates a sample client-server interaction using sockets.

Note
  • This example requires a camera to be physically connected to the running computer. The initialization of the server App and the execution of some commands depend on camera availability.
  • Some commands (e.g., setting the integration time with it=number) will cause the server to broadcast a confirmation message to all connected clients. As a result, each client may receive more messages than it sends.

Build system integration is expected to define PROGRAM_NAME for logging.

Definition in file main.cpp.

Macro Definition Documentation

◆ PROGRAM_NAME

#define PROGRAM_NAME   "client-server-interaction-demo"

Function Documentation

◆ clientThreadBody()

void clientThreadBody ( std::string  clientName,
irsol::types::port_t  port,
std::vector< std::string >  commands 
)

The function executed by each client thread.

Definition at line 47 of file main.cpp.

51{
52 std::random_device rd;
53 std::mt19937 gen(rd());
54 std::uniform_int_distribution<> waitDist(40, 1000); // ms
55
56 // Connect to the server at localhost (it is running on the same machine, in a different thread)
57 std::error_code ec;
58 std::string host = "127.0.0.1";
59 irsol::types::connector_t conn({host, port}, ec);
60 if(ec) {
61 IRSOL_LOG_WARN("Failed to connect to server at {}:{}: {}", host, port, ec.message());
62 return;
63 }
64 IRSOL_NAMED_LOG_INFO(clientName, "Connected to server");
65
66 for(const auto& command : commands) {
67 auto waitMs = waitDist(gen);
68 std::this_thread::sleep_for(std::chrono::milliseconds(waitMs));
69 IRSOL_NAMED_LOG_INFO(clientName, "Sending command: '{}'", command);
70 conn.write(command.data(), command.size());
71
72 char buf[256];
73 auto result = conn.read(buf, sizeof(buf) - 1);
74 if(result.value() > 0) {
75 buf[result.value()] = '\0';
76 IRSOL_NAMED_LOG_INFO(clientName, "Received reply: {}", buf);
77 } else {
78 IRSOL_NAMED_LOG_WARN(clientName, "No reply or connection closed");
79 break;
80 }
81 }
82 IRSOL_NAMED_LOG_INFO(clientName, "Client done");
83}
#define IRSOL_NAMED_LOG_INFO(name,...)
Logs an info-level message using a named logger.
Definition logging.hpp:176
#define IRSOL_LOG_WARN(...)
Logs a warning-level message using the default logger.
Definition logging.hpp:93
#define IRSOL_NAMED_LOG_WARN(name,...)
Logs a warning-level message using a named logger.
Definition logging.hpp:178
sockpp::tcp_connector connector_t
Alias for the TCP client connector type.
Definition types.hpp:71
auto result

◆ getParams()

Params getParams ( int  argc,
char **  argv 
)

Parses command-line arguments using args library.

Supported arguments:

  • --clients, -c: Set number of clients to run concurrently
  • --help, -h: Show help message and exit
Parameters
argcArgument count
argvArgument vector
Returns
Filled Params struct

Definition at line 112 of file main.cpp.

113{
114 args::ArgumentParser parser(getProgramName());
115 args::HelpFlag help(parser, "help", "Display this help menu", {'h', "help"});
116
117 args::ValueFlag<uint32_t> numClientsArg(
118 parser, "#clients", "Number of clients to run concurrently", {'c', "clients"});
119
120 try {
121 parser.ParseCLI(argc, argv);
122 } catch(args::Help) {
123 std::cout << parser.Help() << std::endl;
124 std::exit(0);
125 } catch(args::ParseError& e) {
126 std::cerr << "Error parsing command-line arguments:\n" << e.what() << "\n\n" << parser.Help();
127 std::exit(1);
128 }
129
130 Params params{};
131 if(numClientsArg) {
132 params.numClients = args::get(numClientsArg);
133 }
134 return params;
135}
const std::string getProgramName()
Returns the program name, typically used for logging. If PROGRAM_NAME is not defined at compile time,...
Definition main.cpp:12
Command-line parameters for the program.
uint32_t numClients
Number of clients to run concurrently (default: 1)
Definition main.cpp:99

◆ getProgramName()

const std::string getProgramName ( )

Definition at line 25 of file main.cpp.

26{
27#ifndef PROGRAM_NAME
28#define PROGRAM_NAME "client-server-interaction-demo"
29#endif
30 return PROGRAM_NAME;
31}
#define PROGRAM_NAME

◆ main()

int main ( int  argc,
char **  argv 
)

Main entry point for the handler demo application.

Definition at line 180 of file main.cpp.

181{
182 // Parse command-line parameters
183 Params params = getParams(argc, argv);
184
185 // Construct log file path based on program name
186 std::string logPath = "logs/" + getProgramName() + ".log";
187 irsol::initLogging(logPath.c_str());
188
189 // Enable custom assertion handler
191
192 runDemo(params.numClients);
193 return 0;
194}
Params getParams(int argc, char **argv)
Parses command-line arguments using args library.
Definition main.cpp:54
void runDemo(uint32_t numClients)
Definition main.cpp:138
void initAssertHandler()
Initializes the assertion handler system.
Definition assert.cpp:14
void initLogging(const char *fileSinkFilename="logs/irsol.log", std::optional< spdlog::level::level_enum > minLogLevel=std::nullopt)
Initializes the irsol logging system.
Definition logging.cpp:108

◆ runClientThread()

std::thread runClientThread ( const std::string &  clientName,
irsol::types::port_t  port,
const std::vector< std::string >  commands 
)

TCP client that connects to the server and sends commands at random intervals.

Definition at line 87 of file main.cpp.

91{
92 return std::thread(clientThreadBody, clientName, port, commands);
93}
void clientThreadBody(std::string clientName, irsol::types::port_t port, std::vector< std::string > commands)
The function executed by each client thread.
Definition main.cpp:47

◆ runDemo()

void runDemo ( uint32_t  numClients)

Definition at line 138 of file main.cpp.

139{
140 irsol::types::port_t port = 12345;
141 irsol::server::App app(port);
142
143 // Start server thread
144 std::thread serverThread = runServerThread(app);
145
146 // Start multiple clients
147 std::vector<std::thread> clientThreads;
148 std::vector<std::string> sampleCommands = {"fr?\n",
149 "it=300\n",
150 "fr=10.0\n",
151 "isl=20\n",
152 "isl?\n",
153 "fr=0.5\n",
154 "it=500\n",
155 "fr?\n",
156 "it=1000\n"};
157 for(size_t i = 0; i < numClients; ++i) {
158 std::string clientName = "Client" + std::to_string(i + 1);
159 // Create a shuffled copy of sampleCommands for each client
160 std::vector<std::string> shuffledCommands = sampleCommands;
161 std::shuffle(
162 shuffledCommands.begin(), shuffledCommands.end(), std::mt19937(std::random_device()()));
163 clientThreads.emplace_back(runClientThread(clientName, port, shuffledCommands));
164 }
165
166 // Wait for all clients to finish
167 for(auto& t : clientThreads) {
168 if(t.joinable())
169 t.join();
170 }
171
172 // Stop server and wait for it to finish
173 app.stop();
174 if(serverThread.joinable())
175 serverThread.join();
176}
Main server application that manages client connections and camera streaming.
Definition app.hpp:46
std::thread runClientThread(const std::string &clientName, irsol::types::port_t port, const std::vector< std::string > commands)
TCP client that connects to the server and sends commands at random intervals.
Definition main.cpp:87
std::thread runServerThread(irsol::server::App &app)
Demonstrates handler creation, registration, and dispatch.
Definition main.cpp:35
uint16_t port_t
Represents a network port number. Typically used to specify TCP or UDP ports.
Definition types.hpp:48

◆ runServerThread()

std::thread runServerThread ( irsol::server::App app)

Demonstrates handler creation, registration, and dispatch.

Definition at line 35 of file main.cpp.

36{
37
38 return std::thread([&app]() -> void {
39 if(!app.start()) {
40 IRSOL_LOG_FATAL("Failed to start server.");
41 }
42 });
43}
bool start()
Starts the server.
Definition app.cpp:26