Skip to content
Snippets Groups Projects
Commit 7b1bd202 authored by Saif Eddine Askri's avatar Saif Eddine Askri
Browse files

added request handling

parent 7a3b14f9
Branches
No related tags found
No related merge requests found
add_executable(client client.cpp) add_executable(myclient client.cpp)
add_executable(server server.cpp) add_executable(myserver server.cpp)
add_executable(test test.cpp) add_executable(test test.cpp)
\ No newline at end of file
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#define SERVER_IP "141.100.42.11" //#define SERVER_IP "141.100.42.11"
#define SERVER_IP "127.0.0.1"
#define PORT 2525 #define PORT 2525
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
...@@ -79,6 +81,4 @@ int main(int argc, char* argv[]) { ...@@ -79,6 +81,4 @@ int main(int argc, char* argv[]) {
// Socket schließen // Socket schließen
close(sock); close(sock);
return 0; return 0;
} }
#include <iostream> #include <iostream>
#include <unordered_map>
#include <vector>
#include <thread> #include <thread>
#include <mutex> #include <vector>
#include <condition_variable>
#include <queue>
#include <cstring> #include <cstring>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/epoll.h> #include <mutex>
#define PORT 2525
#define PORT 2525
#define MAX_EVENTS 10
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
#define THREAD_POOL_SIZE 4 #define STORE_OPERATION 's'
#define GET_OPERATION 'g'
#define DELETE_OPERATION 'd'
std::unordered_map<std::string, std::string> store; struct Request {
std::mutex store_mutex; char operation;
std::string key;
std::string value;
};
// Task-Queue für Thread-Pool std::mutex mtx;
std::queue<int> task_queue; std::vector<Request*> DB;
std::mutex queue_mutex;
std::condition_variable cv;
// Worker-Funktion für Thread-Pool
void worker_thread() {
while (true) {
int client_socket;
{
std::unique_lock<std::mutex> lock(queue_mutex);
cv.wait(lock, [] { return !task_queue.empty(); });
client_socket = task_queue.front();
task_queue.pop();
}
char buffer[BUFFER_SIZE] = {0};
ssize_t bytes_received = read(client_socket, buffer, BUFFER_SIZE);
if (bytes_received <= 0) {
close(client_socket);
continue;
}
std::string request(buffer);
if (request.back() != ';') {
std::cerr << "Invalid request format" << std::endl; Request* parseRequest(const char* buffer) {
continue; // Create a new Request struct
Request* req = new Request();
// Copy the input buffer to a mutable string for tokenization
char* input = strdup(buffer); // Duplicate the buffer
if (!input) {
return nullptr; // Handle memory allocation failure
}
// Tokenize the input string using ',' and ';' as delimiters
char* token = strtok(input, ",;");
if (token) {
// First token is the operation
req->operation = token[0]; // Extract the first character (s, g, or d)
// Second token is the key
token = strtok(nullptr, ",;");
if (token) {
req->key = token;
// Third token is the value (only for store operation)
if (req->operation == 's') {
token = strtok(nullptr, ",;");
if (token) {
req->value = token;
}
}
} }
}
// Free the duplicated input string
free(input);
return req;
}
void handle_client(int client_socket) {
char buffer[BUFFER_SIZE] = {0};
// Nachricht vom Client empfangen
ssize_t bytes_received = read(client_socket, buffer, BUFFER_SIZE);
if (bytes_received > 0) {
//std::cout << "Client: " << buffer << std::endl;
Request* request = parseRequest(buffer);
std::string response; std::string response;
char operation = request[0];
size_t first_comma = request.find(',', 1); if(request->operation == STORE_OPERATION){
if (first_comma == std::string::npos) { std::lock_guard<std::mutex> lock(mtx);
response = "ERROR: Invalid format;"; response = "Key " + request->key +" Not Found for [get]";
} else { DB.push_back(request);
std::string key = request.substr(2, first_comma - 2); response = "freue dich :)";
if (operation == 's') { // Store operation }else if (request->operation == GET_OPERATION){
size_t second_comma = request.find(',', first_comma + 1); std::lock_guard<std::mutex> lock(mtx);
if (second_comma == std::string::npos) { for (Request* current : DB) {
response = "ERROR: Invalid format;"; if(current->key == request->key){
} else { response = current->value;
std::string value = request.substr(first_comma + 1, second_comma - first_comma - 1); break;
std::lock_guard<std::mutex> lock(store_mutex);
store[key] = value;
response = "STORED;";
}
} else if (operation == 'g') { // Get operation
std::lock_guard<std::mutex> lock(store_mutex);
auto it = store.find(key);
if (it != store.end()) {
response = "VALUE," + it->second + ";";
} else {
response = "NOT_FOUND;";
} }
} else if (operation == 'd') { // Delete operation }
std::lock_guard<std::mutex> lock(store_mutex); }else if (request->operation == DELETE_OPERATION){
if (store.erase(key) > 0) { std::lock_guard<std::mutex> lock(mtx);
response = "DELETED;"; response = "Key " + request->key +" Not Found for [delete]";
} else { for(size_t i=0; i< DB.size();i++){
response = "NOT_FOUND;"; if(DB[i]->key == request->key){
delete DB[i];
DB.erase(DB.begin() + i);
response = "Key " + request->key +" is deleted";
break;
} }
} else {
response = "ERROR: Unknown operation;";
} }
}else{
response = "bad request -_____- !";
} }
send(client_socket, response.c_str(), response.length(), 0);
// send Response
send(client_socket, response.c_str(), strlen(response.c_str()), 0);
} }
// Socket schließen
close(client_socket);
} }
int main() { int main() {
int server_fd, epoll_fd; int server_fd, client_socket;
struct sockaddr_in address{}; struct sockaddr_in address;
socklen_t addrlen = sizeof(address); socklen_t addrlen = sizeof(address);
std::vector<std::thread> threads;
// Server-Socket erstellen // Socket erstellen
server_fd = socket(AF_INET, SOCK_STREAM, 0); server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) { if (server_fd == -1) {
perror("Socket failed"); perror("Socket failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
int opt = 1; // Serveradresse festlegen
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
address.sin_family = AF_INET; address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT); address.sin_port = htons(PORT);
// Socket an Port binden
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) { if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
perror("Bind failed"); perror("Bind failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (listen(server_fd, SOMAXCONN) < 0) { // Server lauscht auf eingehende Verbindungen
if (listen(server_fd, 5) < 0) {
perror("Listen failed"); perror("Listen failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Epoll erstellen std::cout << "Server listening on port " << PORT << std::endl;
epoll_fd = epoll_create1(0);
if (epoll_fd == -1) {
perror("Epoll create failed");
exit(EXIT_FAILURE);
}
struct epoll_event event{};
event.events = EPOLLIN;
event.data.fd = server_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event) == -1) {
perror("Epoll control failed");
exit(EXIT_FAILURE);
}
std::vector<std::thread> thread_pool;
for (int i = 0; i < THREAD_POOL_SIZE; i++) {
thread_pool.emplace_back(worker_thread);
}
struct epoll_event events[MAX_EVENTS];
while (true) { while (true) {
int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); client_socket = accept(server_fd, (struct sockaddr*)&address, &addrlen);
if (num_events == -1) {
perror("Epoll wait failed"); if (client_socket < 0) {
exit(EXIT_FAILURE); perror("Accept failed");
continue;
} }
for (int i = 0; i < num_events; i++) { std::cout << "New client connected" << std::endl;
if (events[i].data.fd == server_fd) {
int client_socket = accept(server_fd, (struct sockaddr*)&address, &addrlen); // Starte neuen Thread für den Client
if (client_socket < 0) { threads.emplace_back(handle_client, client_socket);
perror("Accept failed"); }
continue;
}
struct epoll_event client_event{};
client_event.events = EPOLLIN;
client_event.data.fd = client_socket;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_socket, &client_event) == -1) { // Alle Threads beenden
perror("Epoll add client failed"); for (auto& t : threads) {
close(client_socket); t.join();
}
} else {
{
std::lock_guard<std::mutex> lock(queue_mutex);
task_queue.push(events[i].data.fd);
}
cv.notify_one();
}
}
} }
close(server_fd); close(server_fd);
return 0; return 0;
} }
#include <iostream>
#include <string>
#include <cstring> // for strtok and strchr
struct Request {
char operation; // Operation: 's' (store), 'g' (get), 'd' (delete)
std::string key; // Key
std::string value; // Value (only for store operation)
};
Request* parseRequest(const char* buffer) {
// Create a new Request struct
Request* req = new Request();
// Copy the input buffer to a mutable string for tokenization
char* input = strdup(buffer); // Duplicate the buffer
if (!input) {
return nullptr; // Handle memory allocation failure
}
// Tokenize the input string using ',' and ';' as delimiters
char* token = strtok(input, ",;");
if (token) {
// First token is the operation
req->operation = token[0]; // Extract the first character (s, g, or d)
// Second token is the key
token = strtok(nullptr, ",;");
if (token) {
req->key = token;
// Third token is the value (only for store operation)
if (req->operation == 's') {
token = strtok(nullptr, ",;");
if (token) {
req->value = token;
}
}
}
}
// Free the duplicated input string
free(input);
return req;
}
int main() {
// Test cases
const char* storeRequest = "s,myKey,myValue;";
const char* getRequest = "g,myKey;";
const char* deleteRequest = "d,myKey;";
// Parse requests
Request* storeReq = parseRequest(storeRequest);
Request* getReq = parseRequest(getRequest);
Request* deleteReq = parseRequest(deleteRequest);
// Print parsed requests
if (storeReq) {
std::cout << "Store Request: Operation=" << storeReq->operation
<< ", Key=" << storeReq->key
<< ", Value=" << storeReq->value << std::endl;
delete storeReq;
}
if (getReq) {
std::cout << "Get Request: Operation=" << getReq->operation
<< ", Key=" << getReq->key << std::endl;
delete getReq;
}
if (deleteReq) {
std::cout << "Delete Request: Operation=" << deleteReq->operation
<< ", Key=" << deleteReq->key << std::endl;
delete deleteReq;
}
return 0;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment