Update Code
This commit is contained in:
parent
dd9d78a923
commit
36ea06260f
@ -30,6 +30,8 @@ namespace math
|
||||
}
|
||||
}
|
||||
|
||||
struct ip_validator { bool operator()(const std::string& addr) const { return net::getaddrinfo(addr, "0") != nullptr; }};
|
||||
|
||||
template<typename T> [[maybe_unused]]
|
||||
T get_input(const std::string& prompt, const std::string& on_error, std::function<bool(T)> validator) noexcept
|
||||
{
|
||||
|
116
main.cpp
116
main.cpp
@ -1,3 +1,5 @@
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "EndlessLoop"
|
||||
#include "modernize/sockets.h"
|
||||
#include "libraries/user_input.h"
|
||||
#include "libraries/osyncstream.h"
|
||||
@ -5,6 +7,7 @@
|
||||
#include "libraries/json.hpp"
|
||||
#include "project/server.h"
|
||||
#include "project/client.h"
|
||||
#include "project/metrics.h"
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
@ -53,52 +56,63 @@ auto get_ip_port(int mode)
|
||||
if (mode == 1)
|
||||
ipaddress = "0.0.0.0";
|
||||
else
|
||||
ipaddress = get_input<std::string>("Enter IP: ");
|
||||
ipaddress = get_input<std::string>("Enter IP: ", "Invalid IP", ip_validator());
|
||||
port = get_input<std::uint16_t>("Enter Port:");
|
||||
return std::make_tuple(mode == 1 ? "Server" : mode == 2 ? "Client" : "Unknown", ipaddress, port);
|
||||
}
|
||||
|
||||
auto execute_as_client(std::string ipaddress, std::uint16_t port)
|
||||
{
|
||||
auto num_clients = get_input<int>("Enter number of clients. (1-25): ", "Invalid Amount", math::is_between<0, 26>);
|
||||
auto operation = get_input<int>("Pick Command\n\t1. Date\n\t2. \n\t3. \n\t4. Netstat\n:>", "Invalid Selection", math::is_between<0, 5>);
|
||||
std::vector<std::thread> threads{};
|
||||
threads.reserve(num_clients);
|
||||
|
||||
auto internal_tracker = 0; //Stats tracking.
|
||||
std::vector<double> internal_stats{};
|
||||
internal_stats.reserve(num_clients);
|
||||
for(int i = 0; i < num_clients; ++i)
|
||||
while(true)
|
||||
{
|
||||
threads.emplace_back(std::thread([&]()
|
||||
{
|
||||
client net_client{};
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
net_client.message_received += [start, &internal_tracker, &internal_stats](std::string& message)
|
||||
{
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double, std::milli> elapsed = end-start;
|
||||
sscout << internal_tracker << math::numerical_suffix(internal_tracker++) << " client response\n"
|
||||
<< message
|
||||
<< "Round Trip Was " << elapsed.count() << " ms\n"
|
||||
<< hr;
|
||||
internal_stats.emplace_back(elapsed.count()); //Stats tracking
|
||||
return true;
|
||||
};
|
||||
auto res = net_client.connect(ipaddress, port);
|
||||
if (res.joinable())
|
||||
{
|
||||
net_client.send_message(std::to_string(operation));
|
||||
res.join();
|
||||
}
|
||||
}));
|
||||
}
|
||||
sscout << "All clients connected.\n" << hr;
|
||||
for(auto&& thread : threads)
|
||||
thread.join();
|
||||
sscout << "Finished!\n";
|
||||
json metrics_json = internal_stats;
|
||||
auto operation = get_input<int>("Pick Command\n\t1. Date\n\t2. \n\t3. \n\t4. Netstat\n\t5.\n\t6.\n\t7. Exit\n:>", "Invalid Selection", math::is_between<0, 8>);
|
||||
if (operation == 7)
|
||||
break;
|
||||
auto num_clients = get_input<int>("Enter number of clients. (1-25): ", "Invalid Amount", math::is_between<0, 26>);
|
||||
std::vector<std::thread> threads{};
|
||||
threads.reserve(num_clients);
|
||||
metrics::job this_job{};
|
||||
this_job.operation = operation;
|
||||
this_job.client_metrics.reserve(num_clients);
|
||||
|
||||
for(int i = 0; i < num_clients; ++i)
|
||||
{
|
||||
threads.emplace_back(std::thread([&]()
|
||||
{
|
||||
client net_client{};
|
||||
metrics::time_tracker clock{};
|
||||
//Callback
|
||||
net_client.message_received += [&](std::string& message)
|
||||
{
|
||||
auto elapsed = clock.elapsed<double, std::milli>();
|
||||
auto client_num = this_job.client_metrics.size()+1;
|
||||
//UX
|
||||
sscout << client_num << math::numerical_suffix(client_num) << " client response\n"
|
||||
<< message
|
||||
<< "Round Trip Was " << elapsed.count() << " ms\n"
|
||||
<< hr;
|
||||
//Metrics
|
||||
metrics::client_message client_metric{};
|
||||
client_metric.client_number = client_num;
|
||||
client_metric.trip_time = elapsed.count();
|
||||
this_job.client_metrics.emplace_back(client_metric); //this isn't thread safe!
|
||||
return true;
|
||||
};
|
||||
auto res = net_client.connect(ipaddress, port);
|
||||
if (res.joinable())
|
||||
{
|
||||
net_client.send_message(std::to_string(operation));
|
||||
res.join();
|
||||
}
|
||||
}));
|
||||
}
|
||||
sscout << "All clients connected.\n" << hr;
|
||||
for(auto&& thread : threads)
|
||||
thread.join();
|
||||
metrics::job_metrics.emplace_back(this_job);
|
||||
sscout << "Finished!\n";
|
||||
}
|
||||
json metrics_json{metrics::job_metrics};
|
||||
std::ofstream metrics;
|
||||
metrics.open ("metrics.json", std::ios::out | std::ios::trunc); //again, metrics data
|
||||
metrics << metrics_json;
|
||||
@ -110,17 +124,17 @@ int main() {
|
||||
net::prologue();
|
||||
const auto mode = get_input<int>("Select Mode\n\t1. Server\n\t2. Client\n>:", "Invalid Choice!",
|
||||
math::is_between<0, 3>);
|
||||
while (true) {
|
||||
auto[prefix, ipaddress, port] = get_ip_port(mode);
|
||||
sscout << prefix << " selected, ip/port is " << ipaddress << "/" << port << ".\n";
|
||||
if (mode == 2) {
|
||||
execute_as_client(ipaddress, port);
|
||||
} else {
|
||||
server net_server{};
|
||||
|
||||
net_server.client_connected += onClientConnected;
|
||||
net_server.message_received += onClientMessaged;
|
||||
net_server.listen(ipaddress, port).join();
|
||||
}
|
||||
auto[prefix, ipaddress, port] = get_ip_port(mode);
|
||||
sscout << prefix << " selected, ip/port is " << ipaddress << "/" << port << ".\n";
|
||||
if (mode == 2) {
|
||||
execute_as_client(ipaddress, port);
|
||||
} else {
|
||||
server net_server{};
|
||||
net_server.client_connected += onClientConnected;
|
||||
net_server.message_received += onClientMessaged;
|
||||
net_server.listen(ipaddress, port).join();
|
||||
}
|
||||
}
|
||||
net::epilogue();
|
||||
return 0;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
@ -25,7 +25,7 @@ public:
|
||||
{
|
||||
const auto address = net::getaddrinfo(ip, std::to_string(port));
|
||||
auto remote_address = net::getaddrinfo(ip, std::to_string(port));
|
||||
if (net::connect(socket, remote_address) < 0)
|
||||
if (!remote_address || net::connect(socket, remote_address) < 0)
|
||||
return std::thread();
|
||||
auto thread = std::thread(&client::accept_message, this);
|
||||
return thread;
|
||||
|
51
project/metrics.h
Normal file
51
project/metrics.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
//#include "libraries/json.hpp"
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace metrics
|
||||
{
|
||||
class time_tracker
|
||||
{
|
||||
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
|
||||
public:
|
||||
template<typename T, typename U>
|
||||
std::chrono::duration<T, U> elapsed() const
|
||||
{
|
||||
return std::chrono::duration<T, U>(std::chrono::high_resolution_clock::now() - start);
|
||||
}
|
||||
};
|
||||
struct client_message
|
||||
{
|
||||
int client_number;
|
||||
double trip_time;
|
||||
};
|
||||
|
||||
inline void to_json(json& j, const client_message& p)
|
||||
{
|
||||
j = json{
|
||||
{ "client_number", p.client_number },
|
||||
{ "trip_time", p.trip_time }
|
||||
};
|
||||
}
|
||||
|
||||
struct job
|
||||
{
|
||||
int operation;
|
||||
std::vector<client_message> client_metrics{};
|
||||
};
|
||||
|
||||
inline void to_json(json& j, const job& p)
|
||||
{
|
||||
auto total_trip_time = 0.;
|
||||
for(auto&& client : p.client_metrics)
|
||||
total_trip_time += client.trip_time;
|
||||
j = json{
|
||||
{ "operation", p.operation },
|
||||
{ "total_trip_time", total_trip_time },
|
||||
{ "average_trip_time",total_trip_time / p.client_metrics.size() },
|
||||
{ "client_metrics", p.client_metrics}
|
||||
};
|
||||
}
|
||||
|
||||
inline std::vector<job> job_metrics{};
|
||||
}
|
Loading…
Reference in New Issue
Block a user