initial commit
This commit is contained in:
commit
1ee3a9863c
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal 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
17
CMakeLists.txt
Normal 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
1
config.ini
Normal file
@ -0,0 +1 @@
|
|||||||
|
address 127.0.0.1
|
||||||
56
src/config.cpp
Normal file
56
src/config.cpp
Normal 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
22
src/config.hpp
Normal 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
22
src/main.cpp
Normal 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
73
src/server.cpp
Normal 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
20
src/server.hpp
Normal 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
9
src/utils.cpp
Normal 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
6
src/utils.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
void stop_program(int signum);
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user