156 lines
4.5 KiB
C++
156 lines
4.5 KiB
C++
|
#include <boost/beast/core.hpp>
|
||
|
#include <boost/beast/websocket.hpp>
|
||
|
#include <boost/asio/connect.hpp>
|
||
|
#include <boost/asio/ip/tcp.hpp>
|
||
|
#include <cstdlib>
|
||
|
#include <iostream>
|
||
|
#include <string>
|
||
|
#include <jsoncpp/json/json.h>
|
||
|
#include <thread>
|
||
|
#include <chrono>
|
||
|
#include <regex>
|
||
|
|
||
|
namespace beast = boost::beast;
|
||
|
namespace websocket = beast::websocket;
|
||
|
namespace net = boost::asio;
|
||
|
using tcp = boost::asio::ip::tcp;
|
||
|
|
||
|
struct Person {
|
||
|
std::string name;
|
||
|
int age;
|
||
|
long long timestamp;
|
||
|
};
|
||
|
|
||
|
Json::Value serializePerson(const Person& person) {
|
||
|
Json::Value jsonPerson;
|
||
|
jsonPerson["name"] = person.name;
|
||
|
jsonPerson["age"] = person.age;
|
||
|
jsonPerson["timestamp"] = static_cast<Json::Value::Int64>(person.timestamp);
|
||
|
return jsonPerson;
|
||
|
}
|
||
|
|
||
|
std::tuple<std::string, std::string, std::string> parseURI(const std::string& uri) {
|
||
|
std::regex uriRegex(R"(^ws://([^:/]+):(\d+)(/.+)$)");
|
||
|
std::smatch match;
|
||
|
|
||
|
if (std::regex_match(uri, match, uriRegex)) {
|
||
|
return std::make_tuple(match[1].str(), match[2].str(), match[3].str());
|
||
|
} else {
|
||
|
throw std::invalid_argument("Nieprawidłowe URI");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
T getInput(const std::string& prompt) {
|
||
|
T value;
|
||
|
while (true) {
|
||
|
std::cout << prompt;
|
||
|
std::cin >> value;
|
||
|
|
||
|
if (std::cin.fail()) {
|
||
|
std::cin.clear();
|
||
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||
|
std::cerr << "Błąd! Spróbuj ponownie." << std::endl;
|
||
|
} else {
|
||
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
void iterateCharBuffer(const char* charBuffer, std::size_t bufferSize) {
|
||
|
for (std::size_t i = 0; i < bufferSize; ++i) {
|
||
|
std::cout << charBuffer[i];
|
||
|
}
|
||
|
std::cout << std::endl;
|
||
|
|
||
|
// Example: Call the function you want to apply to the char buffer
|
||
|
}
|
||
|
|
||
|
int main(int argc, char** argv) {
|
||
|
try {
|
||
|
if (argc != 2) {
|
||
|
std::cerr << "Sposób użycia: " << argv[0] << " <adres URI>\n";
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
|
||
|
std::string uri = argv[1];
|
||
|
auto uriParts = parseURI(uri);
|
||
|
std::string host, port, endpoint;
|
||
|
std::tie(host, port, endpoint) = uriParts;
|
||
|
|
||
|
net::io_context io_context;
|
||
|
|
||
|
websocket::stream<tcp::socket> ws(io_context);
|
||
|
tcp::resolver resolver(io_context);
|
||
|
auto endpoints = resolver.resolve(host, port);
|
||
|
net::connect(ws.next_layer(), endpoints);
|
||
|
|
||
|
ws.handshake(host, endpoint);
|
||
|
|
||
|
while (true) {
|
||
|
std::cout << "Menu:\n";
|
||
|
std::cout << "1. Dodaj rekord\n";
|
||
|
std::cout << "2. Zwróć ostatnie rekordy\n";
|
||
|
std::cout << "3. Wyjście\n";
|
||
|
|
||
|
int choice = getInput<int>("Wybierz opcję: ");
|
||
|
|
||
|
if (choice == 1) {
|
||
|
|
||
|
std::string name = getInput<std::string>("Podaj imię: ");
|
||
|
int age = getInput<int>("Podaj wiek: ");
|
||
|
|
||
|
Person personToSend{name, age, std::chrono::duration_cast<std::chrono::milliseconds>(
|
||
|
std::chrono::system_clock::now().time_since_epoch()).count()};
|
||
|
|
||
|
Json::Value jsonPerson = serializePerson(personToSend);
|
||
|
|
||
|
ws.write(net::buffer(Json::writeString(Json::StreamWriterBuilder(), jsonPerson)));
|
||
|
|
||
|
} else if (choice == 2) {
|
||
|
|
||
|
ws.write(net::buffer("get_latest_records"));
|
||
|
|
||
|
beast::flat_buffer buffer;
|
||
|
ws.read(buffer);
|
||
|
|
||
|
std::cout << "Otrzymano: " << beast::make_printable(buffer.data()) << std::endl;
|
||
|
|
||
|
const char* bufferData = boost::asio::buffer_cast<const char*>(buffer.data());
|
||
|
std::size_t bufferSize = boost::asio::buffer_size(buffer.data());
|
||
|
|
||
|
char* charBuffer = new char[bufferSize + 1];
|
||
|
std::memcpy(charBuffer, bufferData, bufferSize);
|
||
|
charBuffer[bufferSize] = '\0';
|
||
|
|
||
|
iterateCharBuffer(charBuffer, bufferSize);
|
||
|
|
||
|
delete[] charBuffer;
|
||
|
|
||
|
buffer.consume(buffer.size());
|
||
|
|
||
|
} else if (choice == 3) {
|
||
|
|
||
|
std::cout << "Zamykanie programu...\n";
|
||
|
break;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
std::cout << "Nieprawidłowy wybór. Spróbuj ponownie.\n";
|
||
|
|
||
|
}
|
||
|
|
||
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||
|
}
|
||
|
|
||
|
} catch (std::exception const& e) {
|
||
|
std::cerr << "Błąd: " << e.what() << std::endl;
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|