-
ya
- ^-^
- Сообщения: 2336
- Зарегистрирован: 16 дек 2021, 19:56
Сообщение
ya »
server_http_class-001.cpp
Код: Выделить всё
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <mutex>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <cstdlib>
#define PORT 8090
#define BACKLOG 10
#define BUFFER_SIZE 1024
class HttpServer {
public:
void start();
private:
void listenForConnections();
void handleClient(int clientSocket);
std::string processHttpRequest(const std::string& request);
std::string createRedirectResponse(const std::string& host);
};
// start() Основная точка входа для запуска сервера.
void HttpServer::start() {
listenForConnections();
}
// listenForConnections() Метод для прослушивания соединений и передачи их на обработку.
void HttpServer::listenForConnections() {
int serverFd;
struct sockaddr_in address;
int opt = 1;
int addrLen = sizeof(address);
if ((serverFd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("Set socket options failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(serverFd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
if (listen(serverFd, BACKLOG) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
std::cout << "Server is listening on port " << PORT << std::endl;
while (true) {
int newSocket = accept(serverFd, (struct sockaddr *)&address, (socklen_t*)&addrLen);
if (newSocket < 0) {
perror("Accept failed");
continue;
}
// Передаем управление новым клиентом в отдельный поток
std::thread t(&HttpServer::handleClient, this, newSocket);
t.detach();
}
}
// handleClient() Метод для обработки клиента в отдельном потоке.
void HttpServer::handleClient(int clientSocket) {
char buffer[BUFFER_SIZE];
ssize_t bytesRead = recv(clientSocket, buffer, BUFFER_SIZE, 0);
if (bytesRead <= 0) {
std::cerr << "Error reading from socket" << std::endl;
close(clientSocket);
return;
}
std::string request(buffer, bytesRead);
std::cout << "Received request:\n" << request << std::endl;
// Обрабатываем запрос
std::string response = processHttpRequest(request);
if (!response.empty()) {
send(clientSocket, response.c_str(), response.length(), 0);
} else {
// Если ответ пустой, отправляем ошибку
std::string errorResponse = "HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n";
send(clientSocket, errorResponse.c_str(), errorResponse.length(), 0);
}
close(clientSocket); // Закрываем соединение
}
// processHttpRequest() Метод для обработки HTTP-запроса.
std::string HttpServer::processHttpRequest(const std::string& request) {
if (request.substr(0, 3) == "GET") {
size_t pos = request.find("Host:");
if (pos != std::string::npos) {
size_t endPos = request.find("\r\n", pos);
// if (endPos != std::string::npos) {
// std::string host = request.substr(pos + 6, endPos - pos - 6);
// return createRedirectResponse(host);
// }
}
}
// Здесь можно добавить обработку других типов запросов (POST, PUT и т.д.)
return "";
}
// createRedirectResponse() Метод для создания ответа о перенаправлении на HTTPS.
std::string HttpServer::createRedirectResponse(const std::string& host) {
return "HTTP/1.1 301 Moved Permanently\r\n"
"Location: http://" + host + "\r\n"
"Connection: close\r\n"
"\r\n";
}
// Запуск сервера
int main() {
HttpServer server;
server.start();
return 0;
}
Компиляция:
Код: Выделить всё
g++ -std=c++11 -o server_http_class-001 server_http_class-001.cpp -pthread
-
ya
- ^-^
- Сообщения: 2336
- Зарегистрирован: 16 дек 2021, 19:56
Сообщение
ya »
server_http_class-003.cpp
Код: Выделить всё
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <mutex>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <cstdlib>
#define PORT 8090
#define BACKLOG 10
#define BUFFER_SIZE 1024
class View {
public:
virtual std::string render() const = 0;
};
class HomePage : public View {
public:
std::string render() const override {
return "<!DOCTYPE html>\n<html><head><title>Home Page</title></head>"
"<body><h1>Welcome to the Home Page!</h1></body></html>";
}
};
class AboutPage : public View {
public:
std::string render() const override {
return "<!DOCTYPE html>\n<html><head><title>About Us</title></head>"
"<body><h1>About Us</h1><p>This is our about page.</p></body></html>";
}
};
class Controller {
public:
virtual std::string handleRequest(const std::string& path) = 0;
};
class MainController : public Controller {
public:
std::string handleRequest(const std::string& path) override {
if (path == "/") {
HomePage homePage;
return homePage.render();
} else if (path == "/about") {
AboutPage aboutPage;
return aboutPage.render();
} else {
return "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n";
}
}
};
class HttpServer {
public:
void start();
private:
void listenForConnections();
void handleClient(int clientSocket);
std::string processHttpRequest(const std::string& request);
std::string getPathFromRequest(const std::string& request);
};
// start() Основная точка входа для запуска сервера.
void HttpServer::start() {
listenForConnections();
}
// listenForConnections() Метод для прослушивания соединений и передачи их на обработку.
void HttpServer::listenForConnections() {
int serverFd;
struct sockaddr_in address;
int opt = 1;
int addrLen = sizeof(address);
if ((serverFd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("Set socket options failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(serverFd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
if (listen(serverFd, BACKLOG) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
std::cout << "Server is listening on port " << PORT << std::endl;
while (true) {
int newSocket = accept(serverFd, (struct sockaddr *)&address, (socklen_t*)&addrLen);
if (newSocket < 0) {
perror("Accept failed");
continue;
}
// Передаем управление новым клиентом в отдельный поток
std::thread t(&HttpServer::handleClient, this, newSocket);
t.detach();
}
}
// handleClient() Метод для обработки клиента в отдельном потоке.
void HttpServer::handleClient(int clientSocket) {
char buffer[BUFFER_SIZE];
ssize_t bytesRead = recv(clientSocket, buffer, BUFFER_SIZE, 0);
if (bytesRead <= 0) {
std::cerr << "Error reading from socket" << std::endl;
close(clientSocket);
return;
}
std::string request(buffer, bytesRead);
std::cout << "Received request:\n" << request << std::endl;
// Обрабатываем запрос
std::string response = processHttpRequest(request);
if (!response.empty()) {
// Формируем полный HTTP-ответ
std::string fullResponse = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: " + std::to_string(response.length()) + "\r\n"
"Connection: close\r\n"
"\r\n"
+ response;
send(clientSocket, fullResponse.c_str(), fullResponse.length(), 0);
} else {
// Если ответ пустой, отправляем ошибку
std::string errorResponse = "HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n";
send(clientSocket, errorResponse.c_str(), errorResponse.length(), 0);
}
close(clientSocket); // Закрываем соединение
}
// processHttpRequest() Метод для обработки HTTP-запроса.
std::string HttpServer::processHttpRequest(const std::string& request) {
std::string path = getPathFromRequest(request);
MainController controller;
return controller.handleRequest(path);
}
// getPathFromRequest() Метод для извлечения пути из HTTP-запроса.
std::string HttpServer::getPathFromRequest(const std::string& request) {
size_t pos = request.find(' ');
if (pos != std::string::npos) {
size_t endPos = request.find(' ', pos + 1);
if (endPos != std::string::npos) {
return request.substr(pos + 1, endPos - pos - 1);
}
}
return "/"; // Возвращаем корневой путь по умолчанию
}
// Запуск сервера
int main() {
HttpServer server;
server.start();
return 0;
}
Компиляция
Код: Выделить всё
g++ -std=c++11 -o server_http_class-003 server_http_class-003.cpp -pthread
-
ya
- ^-^
- Сообщения: 2336
- Зарегистрирован: 16 дек 2021, 19:56
Сообщение
ya »
server_http_class-005.cpp
Код: Выделить всё
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <mutex>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <unordered_map>// Для std::unordered_map
#include <optional> // Для std::optional
#include <map>
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <memory> // Для std::unique_ptr
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#define PORT 8090
#define BACKLOG 10
#define BUFFER_SIZE 1024
#define HOSTDB "localhost"
#define USERDB "phpmyadmin"
#define PASSDB "1"
#define DBNAME "http004"
class View {
public:
virtual std::string render() const = 0;
};
class HomePage : public View {
public:
std::string render() const override {
return "<!DOCTYPE html>\n<html><head><title>Home Page</title></head>"
"<body><h1>Welcome to the Home Page!</h1></body></html>";
}
};
class AboutPage : public View {
public:
std::string render() const override {
return "<!DOCTYPE html>\n<html><head><title>About Us</title></head>"
"<body><h1>About Us</h1><p>This is our about page.</p></body></html>";
}
};
class GuestBookForm : public View {
public:
std::string render() const override {
return R"(<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Гостевая книга</title>
</head>
<body>
<h1 style="text-align: center;">Добро пожаловать в нашу гостевую книгу!</h1>
<form method="post" action="/guestbook">
<label for="name">Ваше имя:</label>
<input type="text" id="name" name="name"><br>
<textarea rows="5" cols="50" name="message"></textarea><br>
<button type="submit">Отправить сообщение</button>
</form>
</body>
</html>)";
}
};
class Controller {
public:
sql::Driver* driver; // Указатель на драйвер
std::unique_ptr<sql::Connection> con;
Controller() {
try {
driver = get_driver_instance(); // Просто присваиваем указателю
con.reset(driver->connect(HOSTDB, USERDB, PASSDB));
con->setSchema(DBNAME);
} catch (sql::SQLException &e) {
std::cerr << "SQL Exception: " << e.what() << std::endl;
exit(EXIT_FAILURE);
}
}
~Controller() {
// Не нужно освобождать driver, так как он управляется библиотекой
}
virtual std::string handleRequest(const std::string& path) = 0;
protected:
bool saveMessageToDatabase(const std::map<std::string, std::string>& params) {
std::string name = params.at("name");
std::string message = params.at("message");
std::string query = "INSERT INTO guestbook (name, message, datetime_create ) VALUES ('" + name + "', '" + message + "' , NOW() ) ";
try {
std::unique_ptr<sql::PreparedStatement> prep_stmt(con->prepareStatement(query));
prep_stmt->setString(1, name);
prep_stmt->setString(2, message);
prep_stmt->execute();
return true;
} catch(sql::SQLException& e) {
std::cerr << "Error saving message: " << e.what() << '\n';
return false;
}
};
};
class GuestBookController : public Controller {
public:
std::string handleRequest(const std::string& path) override {
if (path == "/guestbook") {
// Логика обработки запроса на гостевую книгу
return GuestBookForm().render();
}
// Обработка других маршрутов
return HomePage().render(); // например
}
};
// Изменение на уровне класса HttpServer
class HttpServer {
public:
void start();
private:
void listenForConnections();
void handleClient(int clientSocket);
std::string processHttpRequest(const std::string& request);
std::string getPathFromRequest(const std::string& request);
};
void HttpServer::start() {
listenForConnections();
}
void HttpServer::listenForConnections() {
int serverFd;
struct sockaddr_in address;
int opt = 1;
socklen_t addrLen = sizeof(address);
if ((serverFd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("Set socket options failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(serverFd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
if (listen(serverFd, BACKLOG) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
std::cout << "Server is listening on port " << PORT << std::endl;
while (true) {
int newSocket = accept(serverFd, nullptr, 0);
if (newSocket < 0) {
perror("Accept failed");
continue;
}
std::thread([this, newSocket] {
handleClient(newSocket);
}).detach();
}
}
// handleClient() Метод для обработки клиента в отдельном потоке.
void HttpServer::handleClient(int clientSocket) {
char buffer[BUFFER_SIZE];
ssize_t bytesRead = recv(clientSocket, buffer, BUFFER_SIZE, 0);
if(bytesRead <= 0) {
std::cerr << "Error reading from socket" << std::endl;
close(clientSocket);
return;
}
std::string request(buffer, bytesRead);
std::cout << "Received request:\n" << request << std::endl;
// Обрабатываем запрос
std::string response = processHttpRequest(request);
if (!response.empty()) {
// Формируем полный HTTP-ответ
std::string fullResponse = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: " + std::to_string(response.length()) + "\r\n"
"Connection: close\r\n"
"\r\n"
+ response;
send(clientSocket, fullResponse.c_str(), fullResponse.length(), 0);
} else {
// Если ответ пустой, отправляем ошибку
std::string errorResponse = "HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n";
send(clientSocket, errorResponse.c_str(), errorResponse.length(), 0);
}
close(clientSocket); // Закрываем соединение
}
// processHttpRequest() Метод для обработки HTTP-запроса.
std::string HttpServer::processHttpRequest(const std::string& request) {
std::string path = getPathFromRequest(request);
GuestBookController controller; // Используем наследника
return controller.handleRequest(path);
}
// getPathFromRequest() Метод для извлечения пути из HTTP-запроса.
std::string HttpServer::getPathFromRequest(const std::string& request) {
size_t pos = request.find(' ');
if (pos != std::string::npos) {
size_t endPos = request.find(' ', pos + 1);
if (endPos != std::string::npos) {
return request.substr(pos + 1, endPos - pos - 1);
}
}
return "/"; // Возвращаем корневой путь по умолчанию
}
// Запуск сервера
int main() {
HttpServer server;
server.start();
return 0;
}
Компиляция:
Код: Выделить всё
g++ -std=c++11 -o server_http_class-005 server_http_class-005.cpp -lmysqlcppconn -lpthread -pthread -lssl -lcrypto