Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 03_UDP/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
main
28 changes: 28 additions & 0 deletions 03_UDP/include/Client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include <stddef.h>
#include <cstdint>
#include <vector>
#include <string>
#include "Network.h"
#include "SimpleChecker.h"

typedef uint64_t calc_t;

class Client
{
private:
static const calc_t CODE_GET_MAX_SIMPLE = 1;
static const calc_t CODE_GET_LAST_N = 2;
static const calc_t CODE_CALCULATE = 3;
static const calc_t CODE_SEND_CALCULATED = 4;

Network _network;

public:
Client(std::string host_name, uint16_t port);

calc_t get_max_prime() const;
std::vector<calc_t> get_last_n(calc_t n) const;
void calculate(calc_t n) const;
};
51 changes: 51 additions & 0 deletions 03_UDP/include/Network.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <stddef.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>

#include <cstdint>
#include <vector>
#include <string>

struct NetworkException
{
private:
std::string message;

public:
NetworkException(std::string message)
: message(message)
{
}

std::string get_message() const
{
return message;
}
};

class Network
{
private:
static const size_t MAX_LEN = 500;
static const size_t TIME_OUT_SEC = 5;

std::string _host_name;
uint16_t _port;

int try_send_message(char* message, size_t message_length, char* response) const;
uint64_t get_check_sum(const std::vector<uint64_t> &v, size_t prefix_length) const;
size_t data2message(const std::vector<uint64_t> &message_data, size_t size_num, char* message) const;
int massage2data(char* response, int response_length, size_t size_num, std::vector<uint64_t> &response_data) const;

public:
Network(std::string host_name, uint16_t port);

std::vector<uint64_t> send_message(const std::vector<uint64_t> &v, size_t size_num) const;
};
14 changes: 14 additions & 0 deletions 03_UDP/include/SimpleChecker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <stddef.h>
#include <cstdint>
#include <vector>

class SimpleChecker
{
public:
SimpleChecker() = delete;

static bool is_prime(uint64_t n);
static std::vector<uint64_t> check_interval(uint64_t start_num, size_t n);
};
70 changes: 70 additions & 0 deletions 03_UDP/src/Client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "Client.h"

using std::string;
using std::vector;

Client::Client(string host_name, uint16_t port)
: _network(host_name, port)
{
}

calc_t Client::get_max_prime() const
{
vector<uint64_t> message;
message.push_back((uint64_t)CODE_GET_MAX_SIMPLE);

vector<uint64_t> response;
do {
response = _network.send_message(message, sizeof(calc_t));
} while (response.size() != 1);

calc_t res = (calc_t)response[0];
return res;
}

vector<calc_t> Client::get_last_n(calc_t n) const
{
vector<uint64_t> message;
message.push_back((uint64_t)CODE_GET_LAST_N);
message.push_back((uint64_t)n);

vector<uint64_t> response;
do {
response = _network.send_message(message, sizeof(calc_t));
} while (response.size() == 0 || response[0] + 1 != response.size());

vector<calc_t> res;
for (size_t i = 1; i < response.size(); i++) {
res.push_back((calc_t)response[i]);
}
return res;
}

void Client::calculate(calc_t n) const
{
vector<uint64_t> message;
message.push_back((uint64_t)CODE_CALCULATE);
message.push_back((uint64_t)n);

vector<uint64_t> response;
do {
response = _network.send_message(message, sizeof(calc_t));
} while (response.size() != 1);

calc_t start_num = (calc_t)response[0];

vector<uint64_t> prime_nums = SimpleChecker::check_interval(start_num, n);

message.clear();
message.push_back((uint64_t)CODE_SEND_CALCULATED);
message.push_back((uint64_t)n);
message.push_back((uint64_t)start_num);
message.push_back((uint64_t)prime_nums.size());
for (uint64_t x : prime_nums) {
message.push_back(x);
}

do {
response = _network.send_message(message, sizeof(calc_t));
} while (response.size() != 0);
}
121 changes: 121 additions & 0 deletions 03_UDP/src/Network.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include "Network.h"

using std::vector;
using std::string;

Network::Network(string host_name, uint16_t port)
: _host_name(host_name), _port(port)
{}

int Network::try_send_message(char* message, size_t message_length, char* response) const
{
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
throw NetworkException("Could not open socket");
}

struct hostent *server = gethostbyname(_host_name.c_str());

if (server == NULL) {
throw NetworkException("Could not find host");
}

struct sockaddr_in serv_addr;
memset((char*)&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy(server->h_addr, (char*) &serv_addr.sin_addr.s_addr, (size_t) server->h_length);
serv_addr.sin_port = htons(_port);

struct timeval tv;
tv.tv_sec = TIME_OUT_SEC;
tv.tv_usec = 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
throw NetworkException("Could not set timeout");
}

int n;
n = sendto(sockfd, (const char *)message, message_length, MSG_CONFIRM, (const struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (n == -1) {
close(sockfd);
return -1;
}

socklen_t len;
n = recvfrom(sockfd, (char *)response, MAX_LEN, MSG_WAITALL, (struct sockaddr *) &serv_addr, &len);

close(sockfd);
return n;
}

uint64_t Network::get_check_sum(const vector<uint64_t> &v, size_t prefix_length) const
{
size_t len = v.size();
if (len > prefix_length) {
len = prefix_length;
}

uint64_t sum = 0;
for (size_t i = 0; i < len; i++) {
sum += v[i];
}

return sum;
}

size_t Network::data2message(const vector<uint64_t> &message_data, size_t size_num, char* message) const
{
char* pointer = message;
for (uint64_t x : message_data) {
bcopy((const char *)&x, pointer, size_num);
pointer += size_num;
}

uint64_t sum = get_check_sum(message_data, message_data.size());
bcopy((const char *)&sum, pointer, size_num);
pointer += size_num;

return size_num * (message_data.size() + 1);
}

int Network::massage2data(char* response, int response_length, size_t size_num, vector<uint64_t> &response_data) const
{
if (response_length == -1 || response_length == 0) {
return -1;
}

if (response_length % size_num != 0) {
return -1;
}

char* pointer = response;
response_length /= size_num;
while (response_length--) {
uint64_t x;
bcopy(pointer, (char *)&x, size_num);
pointer += size_num;
response_data.push_back(x);
}

if (response_data.back() != get_check_sum(response_data, response_data.size() - 1)) {
return -1;
}

response_data.pop_back();

return 0;
}

vector<uint64_t> Network::send_message(const vector<uint64_t> &message_data, size_t size_num) const
{
char message[MAX_LEN];
size_t message_length = data2message(message_data, size_num, message);

char response[MAX_LEN];
int response_length;
vector<uint64_t> response_data;
do {
response_length = try_send_message(message, message_length, response);
} while (massage2data(response, response_length, size_num, response_data) == -1);

return response_data;
}
27 changes: 27 additions & 0 deletions 03_UDP/src/SimpleChecker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "SimpleChecker.h"

using std::vector;

bool SimpleChecker::is_prime(uint64_t n)
{
if (n < 2)
return false;

for (uint64_t d = 2; d*d <= n; d++)
if ((n / d) * d == n)
return false;
return true;
}

vector<uint64_t> SimpleChecker::check_interval(uint64_t start_num, size_t n)
{
vector<uint64_t> res;

for (size_t dx = 0; dx < n; dx++) {
size_t x = start_num + dx;
if (is_prime(x))
res.push_back(x);
}

return res;
}
Loading