Clean up part 2.
This commit is contained in:
parent
360d8325f4
commit
c6851bd893
@ -2,5 +2,4 @@ cmake_minimum_required(VERSION 3.17)
|
|||||||
project(Project_1)
|
project(Project_1)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
add_executable(Project_1 main.cpp modernize/sockets.cpp)
|
add_executable(Project_1 main.cpp modernize/sockets.cpp)
|
Binary file not shown.
1
cmake-build-debug/metrics.json
Normal file
1
cmake-build-debug/metrics.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[15.534375,22.479834,28.15575]
|
108
main.cpp
108
main.cpp
@ -5,95 +5,14 @@
|
|||||||
#include "libraries/user_input.h"
|
#include "libraries/user_input.h"
|
||||||
#include "libraries/osyncstream.h"
|
#include "libraries/osyncstream.h"
|
||||||
#include "libraries/terminal.h"
|
#include "libraries/terminal.h"
|
||||||
|
#include "libraries/json.hpp"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iomanip>
|
#include "project/server.h"
|
||||||
#include "server.h"
|
#include "project/client.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
auto server(const addrinfo_up& address) noexcept -> void
|
|
||||||
{
|
|
||||||
|
|
||||||
const auto socket = net::socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
net::bind(socket, address);
|
|
||||||
net::listen(socket);
|
|
||||||
std::cout << "[ Server Started ]" << std::endl;
|
|
||||||
|
|
||||||
//below needs update.
|
|
||||||
do
|
|
||||||
{
|
|
||||||
auto const client = accept(socket, nullptr, nullptr);
|
|
||||||
if (!client)
|
|
||||||
continue;
|
|
||||||
printf("Got a client.\n");
|
|
||||||
|
|
||||||
|
|
||||||
auto operation = net::recv(client);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (std::stoi(operation))
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
net::send(client, net::system("date /t"));
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
net::send(client, net::system("netstat -ant"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
net::send(client, "INVALID INPUT!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (std::exception&)
|
|
||||||
{
|
|
||||||
net::send(client, "INVALID INPUT!");
|
|
||||||
}
|
|
||||||
net::send(client, "<=> T123 <=>");
|
|
||||||
net::closesocket(client);
|
|
||||||
printf("Closed Client\n");
|
|
||||||
|
|
||||||
} while (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto client(const addrinfo_up& address) noexcept -> void
|
|
||||||
{
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
const auto operation = get_input<unsigned int>("Select Command:\n\t1. Date", "");
|
|
||||||
const auto total_clients = get_input<unsigned int>("Input Number of Clients: ", "");
|
|
||||||
|
|
||||||
std::vector<std::thread> threads;
|
|
||||||
|
|
||||||
for(auto i = 0u; i < total_clients; ++i)
|
|
||||||
{
|
|
||||||
const auto prefix = "[client " + std::to_string(i) + "]: ";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
threads.emplace_back(std::thread([=, &address]()
|
|
||||||
{
|
|
||||||
sscout << prefix << "started" << std::endl;
|
|
||||||
const auto socket = net::socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
net::connect(socket, address);
|
|
||||||
net::send(socket, std::to_string(operation));
|
|
||||||
sscout << prefix << "sent command" << std::endl;
|
|
||||||
const auto& response = net::recv(socket);
|
|
||||||
sscout << prefix << "got response\n" << prefix << response << std::endl;
|
|
||||||
net::closesocket(socket);
|
|
||||||
sscout << prefix << "closed" << std::endl;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
catch (std::exception&) { sscout << prefix << " failed to init " << std::endl; }
|
|
||||||
}
|
|
||||||
for (auto& thread : threads)
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
auto onClientConnected(networked& client)
|
auto onClientConnected(networked& client)
|
||||||
{
|
{
|
||||||
@ -146,16 +65,19 @@ 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 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>);
|
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>);
|
||||||
auto internal_tracker = 0;
|
|
||||||
std::vector<std::thread> threads{};
|
std::vector<std::thread> threads{};
|
||||||
threads.reserve(num_clients);
|
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)
|
for(int i = 0; i < num_clients; ++i)
|
||||||
{
|
{
|
||||||
threads.emplace_back(std::thread([&]()
|
threads.emplace_back(std::thread([&]()
|
||||||
{
|
{
|
||||||
client net_client{};
|
client net_client{};
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
net_client.message_received += [start, &internal_tracker](std::string& message)
|
net_client.message_received += [start, &internal_tracker, &internal_stats](std::string& message)
|
||||||
{
|
{
|
||||||
auto end = std::chrono::high_resolution_clock::now();
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
std::chrono::duration<double, std::milli> elapsed = end-start;
|
std::chrono::duration<double, std::milli> elapsed = end-start;
|
||||||
@ -163,7 +85,7 @@ auto execute_as_client(std::string ipaddress, std::uint16_t port)
|
|||||||
<< message
|
<< message
|
||||||
<< "Round Trip Was " << elapsed.count() << " ms\n"
|
<< "Round Trip Was " << elapsed.count() << " ms\n"
|
||||||
<< hr;
|
<< hr;
|
||||||
|
internal_stats.emplace_back(elapsed.count()); //Stats tracking
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
auto res = net_client.connect(ipaddress, port);
|
auto res = net_client.connect(ipaddress, port);
|
||||||
@ -178,6 +100,12 @@ auto execute_as_client(std::string ipaddress, std::uint16_t port)
|
|||||||
for(auto&& thread : threads)
|
for(auto&& thread : threads)
|
||||||
thread.join();
|
thread.join();
|
||||||
sscout << "Finished!\n";
|
sscout << "Finished!\n";
|
||||||
|
json metrics_json = internal_stats;
|
||||||
|
|
||||||
|
std::ofstream metrics;
|
||||||
|
metrics.open ("metrics.json", std::ios::out | std::ios::trunc); //again, metrics data
|
||||||
|
metrics << metrics_json;
|
||||||
|
metrics.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BIN
project/.DS_Store
vendored
Normal file
BIN
project/.DS_Store
vendored
Normal file
Binary file not shown.
33
project/client.h
Normal file
33
project/client.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../libraries/event.h"
|
||||||
|
#include "networked.h"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
class client : public networked
|
||||||
|
{
|
||||||
|
auto accept_message() -> void //add const later
|
||||||
|
{
|
||||||
|
while(is_valid()) /* Accept all messages */
|
||||||
|
{
|
||||||
|
auto message = receive_message();
|
||||||
|
if (message.empty() && is_valid()) //connection is closed or broken.
|
||||||
|
{
|
||||||
|
disconnect();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
message_received.execute(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
event<std::string&> message_received {};
|
||||||
|
explicit client() : networked(net::socket(AF_INET, SOCK_STREAM, 0)){}
|
||||||
|
auto connect(const std::string& ip, const port port) -> std::thread
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
return std::thread();
|
||||||
|
auto thread = std::thread(&client::accept_message, this);
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
};
|
22
project/networked.h
Normal file
22
project/networked.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../modernize/sockets.h"
|
||||||
|
|
||||||
|
class networked
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
SOCKET socket;
|
||||||
|
public:
|
||||||
|
explicit networked(SOCKET existing)
|
||||||
|
{
|
||||||
|
socket = existing;
|
||||||
|
}
|
||||||
|
auto disconnect() -> void
|
||||||
|
{
|
||||||
|
if (!is_valid()) return; //socket is closed.
|
||||||
|
net::closesocket(socket);
|
||||||
|
socket = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
[[nodiscard]] auto receive_message() const -> std::string { if (!is_valid()) return ""; return net::recv(socket); }
|
||||||
|
auto send_message(const std::string& message) const -> void { if (!is_valid()) return; net::send(socket, message);}
|
||||||
|
[[nodiscard]] auto is_valid() const -> bool { return socket != INVALID_SOCKET; }
|
||||||
|
};
|
58
project/server.h
Executable file
58
project/server.h
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../libraries/event.h"
|
||||||
|
#include "../libraries/osyncstream.h"
|
||||||
|
#include "networked.h"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
class server : networked
|
||||||
|
{
|
||||||
|
auto accept_clients() -> void
|
||||||
|
{
|
||||||
|
while(is_valid())
|
||||||
|
{
|
||||||
|
auto client = networked(accept(socket, nullptr, nullptr));
|
||||||
|
client_connected.execute(client);
|
||||||
|
#ifdef THREADED
|
||||||
|
std::thread(&server::accept_client_message, this, client).detach();
|
||||||
|
#else
|
||||||
|
std::thread(&server::accept_client_message, this, client).join();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto accept_client_message(networked client) -> void //add const later
|
||||||
|
{
|
||||||
|
while(client.is_valid()) /* Accept all messages */
|
||||||
|
{
|
||||||
|
auto message = client.receive_message();
|
||||||
|
if (message.empty() && client.is_valid()) //Client could have disconnected after check but PRIOR to recv.
|
||||||
|
{
|
||||||
|
sscout << "Client Connection Lost\n";
|
||||||
|
client.disconnect();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
message_received.execute(client, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
event<networked&> client_connected {};
|
||||||
|
event<networked&, std::string&> message_received {};
|
||||||
|
auto listen(const std::string& ip, const port port) -> std::thread
|
||||||
|
{
|
||||||
|
const auto address = net::getaddrinfo(ip, std::to_string(port));
|
||||||
|
if (net::bind(socket, address) < 0)
|
||||||
|
{
|
||||||
|
sscout << "Error binding.\n";
|
||||||
|
return std::thread();
|
||||||
|
}
|
||||||
|
if (net::listen(socket) < 0)
|
||||||
|
{
|
||||||
|
sscout << "Error listening.\n";
|
||||||
|
return std::thread();
|
||||||
|
}
|
||||||
|
sscout << "Listening ... \n";
|
||||||
|
return std::thread(&server::accept_clients, this);
|
||||||
|
}
|
||||||
|
explicit server() : networked(net::socket(AF_INET, SOCK_STREAM, 0)){}
|
||||||
|
};
|
112
server.h
112
server.h
@ -1,112 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "modernize/sockets.h"
|
|
||||||
#include "libraries/event.h"
|
|
||||||
#include "libraries/osyncstream.h"
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class networked
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
SOCKET socket;
|
|
||||||
public:
|
|
||||||
explicit networked(SOCKET existing)
|
|
||||||
{
|
|
||||||
socket = existing;
|
|
||||||
}
|
|
||||||
auto disconnect() -> void
|
|
||||||
{
|
|
||||||
if (!is_valid()) return; //socket is closed.
|
|
||||||
net::closesocket(socket);
|
|
||||||
socket = INVALID_SOCKET;
|
|
||||||
}
|
|
||||||
[[nodiscard]] auto receive_message() const -> std::string { if (!is_valid()) return ""; return net::recv(socket); }
|
|
||||||
auto send_message(const std::string& message) const -> void { if (!is_valid()) return; net::send(socket, message);}
|
|
||||||
[[nodiscard]] auto is_valid() const -> bool { return socket != INVALID_SOCKET; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class client : public networked
|
|
||||||
{
|
|
||||||
auto accept_message() -> void //add const later
|
|
||||||
{
|
|
||||||
while(is_valid()) /* Accept all messages */
|
|
||||||
{
|
|
||||||
auto message = receive_message();
|
|
||||||
if (message.empty() && is_valid()) //connection is closed or broken.
|
|
||||||
{
|
|
||||||
disconnect();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
message_received.execute(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
event<std::string&> message_received {};
|
|
||||||
explicit client() : networked(net::socket(AF_INET, SOCK_STREAM, 0)){}
|
|
||||||
auto connect(const std::string& ip, const port port) -> std::thread
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
return std::thread();
|
|
||||||
auto thread = std::thread(&client::accept_message, this);
|
|
||||||
return thread;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class server : networked
|
|
||||||
{
|
|
||||||
auto accept_clients() -> void
|
|
||||||
{
|
|
||||||
while(is_valid())
|
|
||||||
{
|
|
||||||
auto client = networked(accept(socket, nullptr, nullptr));
|
|
||||||
client_connected.execute(client);
|
|
||||||
#ifdef THREADED
|
|
||||||
std::thread(&server::accept_client_message, this, client).detach();
|
|
||||||
#else
|
|
||||||
std::thread(&server::accept_client_message, this, client).join();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto accept_client_message(networked client) -> void //add const later
|
|
||||||
{
|
|
||||||
//using namespace std::chrono_literals;
|
|
||||||
//std::this_thread::sleep_for(2000ms);
|
|
||||||
while(client.is_valid()) /* Accept all messages */
|
|
||||||
{
|
|
||||||
auto message = client.receive_message();
|
|
||||||
if (message.empty() && client.is_valid()) //Client could have disconnected after check but PRIOR to recv.
|
|
||||||
{
|
|
||||||
sscout << "Client Connection Lost\n";
|
|
||||||
client.disconnect();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
message_received.execute(client, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
event<networked&> client_connected {};
|
|
||||||
event<networked&, std::string&> message_received {};
|
|
||||||
auto listen(const std::string& ip, const port port) -> std::thread
|
|
||||||
{
|
|
||||||
const auto address = net::getaddrinfo(ip, std::to_string(port));
|
|
||||||
if (net::bind(socket, address) < 0)
|
|
||||||
{
|
|
||||||
sscout << "Error binding.\n";
|
|
||||||
return std::thread();
|
|
||||||
}
|
|
||||||
if (net::listen(socket) < 0)
|
|
||||||
{
|
|
||||||
sscout << "Error listening.\n";
|
|
||||||
return std::thread();
|
|
||||||
}
|
|
||||||
sscout << "Listening ... \n";
|
|
||||||
return std::thread(&server::accept_clients, this);
|
|
||||||
}
|
|
||||||
explicit server() : networked(net::socket(AF_INET, SOCK_STREAM, 0)){}
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user