initial commit

This commit is contained in:
Илья Глазунов 2026-01-09 16:37:47 +03:00
commit 1ee3a9863c
10 changed files with 240 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
CMakeCache.txt
CMakeFiles/
Makefile
cmake_install.cmake
install_local_manifest.txt
install_manifest.txt
install_prefix.txt
install_strip.txt
install_strip_local.txt
install_strip_local_manifest.txt
install_strip_local_manifest.txt
.vscode/
my_own_redis

17
CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.10)
project(MyOwnRedis)
set(CMAKE_CXX_STANDART 17)
set(CMAKE_CXX_REQUIRED ON)
set(SOURCES
src/main.cpp
src/utils.cpp
src/config.cpp
src/server.cpp
)
add_executable(my_own_redis ${SOURCES})

1
config.ini Normal file
View File

@ -0,0 +1 @@
address 127.0.0.1

56
src/config.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "config.hpp"
#include <fstream>
#include <stdexcept>
#include <iostream>
Config::Config(const std::string& filename) {
if (filename.empty()) {
std::cerr << "Filename is empty\nUsing default filename: config.ini\n";
}
load_from_file(filename);
check_required_keys();
}
void Config::load_from_file(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Failed to open config file: " << filename << "\n";
std::cout << "Using default parameters: 127.0.0.1:6379\n";
address = "127.0.0.1";
port = 6379;
return;
}
std::string key;
while (file >> key) {
if (key == "address") {
file >> address;
} else if (key == "port") {
file >> port;
} else {
std::cerr << "Unknown key: " << key << "\n";
continue;
}
}
file.close();
}
std::string Config::get_address() const {
return address;
}
int Config::get_port() const {
return port;
}
void Config::check_required_keys() const {
if (address.empty()) {
std::cerr << "Address is not set\n";
exit(EXIT_FAILURE);
}
if (port == 0 ) {
std::cerr << "Port is not set\n";
exit(EXIT_FAILURE);
}
}

22
src/config.hpp Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <string>
#include <map>
class Config {
public:
// Конструктор
Config(const std::string& filename = "config.ini");
// Геттеры
std::string get_address() const;
int get_port() const;
void check_required_keys() const;
private:
std::string address;
int port;
void load_from_file(const std::string& filename);
};

22
src/main.cpp Normal file
View File

@ -0,0 +1,22 @@
#include <iostream>
#include <csignal>
#include "config.hpp"
#include "server.hpp"
#include "utils.hpp"
int main() {
std::signal(SIGINT, stop_program);
try {
Config config("config.ini");
config.check_required_keys();
Server server(config);
server.run();
} catch (const std::exception& e) {
std::cerr << "Fatal error: " << e.what() << "\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

73
src/server.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "server.hpp"
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
Server::Server(const Config& config)
: address(config.get_address()), port(config.get_port()), sockfd(-1) {
}
Server::~Server() {
if (sockfd != -1) {
close(sockfd);
}
}
void Server::setup() {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
throw std::runtime_error("Error creating socket");
}
int val = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (inet_pton(AF_INET, address.c_str(), &addr.sin_addr) != 1) {
throw std::runtime_error("Error parsing address: " + address);
}
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
throw std::runtime_error("Error binding to " + address + ":" + std::to_string(port));
}
if (listen(sockfd, SOMAXCONN) < 0) {
throw std::runtime_error("Error listening for connections");
}
std::cout << "Server started on " << address << ":" << port << "\n";
}
void Server::handle_connection(int connectionfd) {
char rbuf[64] = {};
ssize_t n = read(connectionfd, rbuf, sizeof(rbuf) - 1);
if (n < 0) {
std::cerr << "Error reading client packet\n";
return;
}
std::cout << "Client says: " << std::string(rbuf, n) << "\n";
ssize_t written = write(connectionfd, "Hello, client!\n", 14);
if (written < 0) {
std::cerr << "Error writing to client\n";
}
}
void Server::run() {
setup();
while (true) {
struct sockaddr_in client_addr = {};
socklen_t addrlen = sizeof(client_addr);
int connectionfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
if (connectionfd < 0) {
continue;
}
handle_connection(connectionfd);
close(connectionfd);
}
}

20
src/server.hpp Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <string>
#include "config.hpp"
class Server {
public:
Server(const Config& config);
~Server();
void run();
private:
int sockfd;
std::string address;
int port;
void handle_connection(int connectionfd);
void setup();
};

9
src/utils.cpp Normal file
View File

@ -0,0 +1,9 @@
#include <iostream>
#include <cstdlib>
#include <string>
void stop_program(int signum) {
std::cout << "\nInterrupt signal (" << signum << ") received.\n";
std::cout << "Exiting program...\n";
exit(signum);
}

6
src/utils.hpp Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <netinet/in.h>
void stop_program(int signum);