From f79a906ee79c5f388942bb5224e8a9b09ae2acd1 Mon Sep 17 00:00:00 2001 From: lingel <2894340009@qq.com> Date: Mon, 17 Jun 2024 19:09:39 +0800 Subject: [PATCH] 11 --- .../epollip/connector_controller.cpp | 288 ++++++++++++++++++ .../epollip/connector_database.cpp | 31 ++ .../epollip/connector_gateway.cpp | 86 ++++++ .../epollip/db_processer/basic_db.cpp | 66 ++++ .../interface/connector_controller.cpp | 280 +++++++++++++++++ .../epollip/interface/connector_controller.h | 22 ++ .../epollip/interface/connector_database.cpp | 68 +++++ .../epollip/interface/connector_database.h | 10 + .../epollip/interface/main.cpp | 35 +++ .../epollip/interface/main_program | Bin 0 -> 90968 bytes src/controller-v1.1/epollip/new_client.cpp | 125 ++++++++ src/controller/connector_controller.cpp | 288 ++++++++++++++++++ src/controller/connector_database.cpp | 31 ++ src/controller/connector_gateway.cpp | 86 ++++++ src/controller/db_processer/basic_db.cpp | 66 ++++ .../interface/connector_controller.cpp | 280 +++++++++++++++++ .../interface/connector_controller.h | 22 ++ .../interface/connector_database.cpp | 68 +++++ src/controller/interface/connector_database.h | 10 + src/controller/interface/main.cpp | 35 +++ src/controller/interface/main_program | Bin 0 -> 90968 bytes src/controller/new_client.cpp | 125 ++++++++ 22 files changed, 2022 insertions(+) create mode 100644 src/controller-v1.1/epollip/connector_controller.cpp create mode 100644 src/controller-v1.1/epollip/connector_database.cpp create mode 100644 src/controller-v1.1/epollip/connector_gateway.cpp create mode 100644 src/controller-v1.1/epollip/db_processer/basic_db.cpp create mode 100644 src/controller-v1.1/epollip/interface/connector_controller.cpp create mode 100644 src/controller-v1.1/epollip/interface/connector_controller.h create mode 100644 src/controller-v1.1/epollip/interface/connector_database.cpp create mode 100644 src/controller-v1.1/epollip/interface/connector_database.h create mode 100644 src/controller-v1.1/epollip/interface/main.cpp create mode 100644 src/controller-v1.1/epollip/interface/main_program create mode 100644 src/controller-v1.1/epollip/new_client.cpp create mode 100644 src/controller/connector_controller.cpp create mode 100644 src/controller/connector_database.cpp create mode 100644 src/controller/connector_gateway.cpp create mode 100644 src/controller/db_processer/basic_db.cpp create mode 100644 src/controller/interface/connector_controller.cpp create mode 100644 src/controller/interface/connector_controller.h create mode 100644 src/controller/interface/connector_database.cpp create mode 100644 src/controller/interface/connector_database.h create mode 100644 src/controller/interface/main.cpp create mode 100644 src/controller/interface/main_program create mode 100644 src/controller/new_client.cpp diff --git a/src/controller-v1.1/epollip/connector_controller.cpp b/src/controller-v1.1/epollip/connector_controller.cpp new file mode 100644 index 0000000..6b0d54c --- /dev/null +++ b/src/controller-v1.1/epollip/connector_controller.cpp @@ -0,0 +1,288 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 1024 +#define HTTP_SERVER_PORT 8080 + +std::vector threads; // 存储所有连接线程 +std::map sockets; // 存储套接字 +std::mutex sockets_mutex; // 用于同步访问 sockets +std::atomic exit_flag(false); // 原子退出标志 + + +// 维护连接的函数 +void KeepConnection(int sock) { + char buffer[BUFFER_SIZE]; + int nbytes; + while (!exit_flag) { + nbytes = recv(sock, buffer, BUFFER_SIZE, 0); + if (nbytes <= 0) { + std::cout << "Gateway disconnected" << std::endl; + break; + } + std::cout << "Received from gateway (Socket " << sock << "): " << buffer << std::endl; + } + + { + std::lock_guard lock(sockets_mutex); + sockets.erase(sock); // 从集合中移除套接字 + } + close(sock); +} +// 连接到网关的函数 +void ConnectToGateway(const std::string& ip, int port) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("Could not create socket"); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) { + perror("Invalid address"); + close(sock); + return; + } + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Connection to the server failed"); + close(sock); + return; + } + + { + std::lock_guard lock(sockets_mutex); + sockets[sock] = 1; // 将套接字添加到集合中 + } + + std::cout << "Connected to gateway at " << ip << ":" << port << " (Socket " << sock << ")" << std::endl; + + // 在新线程中维护连接 + threads.emplace_back(KeepConnection, sock); +} + +// 处理HTTP请求的函数 +void HandleHttpRequest(int client_socket) { + char buffer[BUFFER_SIZE]; + int bytes_read = recv(client_socket, buffer, sizeof(buffer), 0); + if (bytes_read <= 0) { + close(client_socket); + return; + } + + // 简单解析HTTP请求 + std::string http_request(buffer, bytes_read); + std::string ip; + int port; + + // 寻找IP和端口号 + auto host_pos = http_request.find("Host: "); + if (host_pos != std::string::npos) { + auto start = host_pos + std::string("Host: ").size(); + ip = http_request.substr(start, http_request.find("\r\n", start) - start); + } + + auto content_length_pos = http_request.find("Content-Length:"); + if (content_length_pos != std::string::npos) { + auto start = content_length_pos + std::string("Content-Length: ").size(); + int length = std::stoi(http_request.substr(start, http_request.find("\r\n", start) - start)); + if (length > 0) { + char* content = new char[length]; + bytes_read = recv(client_socket, content, length, 0); + if (bytes_read > 0) { + // 解析JSON内容(假设前端发送的是JSON格式) + // 这里需要添加JSON解析逻辑来提取IP和端口 + // 示例:{"ip":"192.168.1.1","port":8080} + // 可以使用第三方库如nlohmann/json来解析JSON + + // 假设解析后得到ip和port + // ConnectToGateway(ip, port); + + delete[] content; + } + } + } + + // 发送HTTP响应 + std::string response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; + send(client_socket, response.c_str(), response.size(), 0); + close(client_socket); +} + +// 启动HTTP服务器的函数 +void StartHttpServer() { + int http_server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (http_server_socket < 0) { + perror("Could not create HTTP server socket"); + return; + } + + int opt = 1; + if (setsockopt(http_server_socket, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("Setsockopt failed"); + close(http_server_socket); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(HTTP_SERVER_PORT); + + if (bind(http_server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Bind failed"); + close(http_server_socket); + return; + } + + if (listen(http_server_socket, 5) < 0) { + perror("Listen failed"); + close(http_server_socket); + return; + } + + std::cout << "HTTP server listening on port " << HTTP_SERVER_PORT << std::endl; + + while (!exit_flag) { + int client_socket = accept(http_server_socket, NULL, NULL); + if (client_socket < 0) { + perror("Accept failed"); + continue; + } + + threads.emplace_back(HandleHttpRequest, client_socket); + } + + close(http_server_socket); +} + +int main() { + // threads.emplace_back(StartHttpServer); + + // std::string command, ip; + // int port; + // bool in_connect_mode = false; + // std::cout << "Enter command (connect/exit): "; + // while (true) { + + // if (in_connect_mode) + // { + // std::cout << "continue connect or not ? (y or n) "; + // std::cin >> command; + // if(command=="y"){ + // std::cout << "Enter the gateway IP address: "; + // std::cin >> ip; + // std::cout << "Enter the gateway port: "; + // std::cin >> port; + // ConnectToGateway(ip, port); + // } + // else { + // in_connect_mode = false; // 退出连接模式 + // std::cout << "Exiting connect mode." << std::endl; + // } + // } + // else{ + // std::cout << "Enter command (connect/exit): "; + // std::cin>>command; + // if (command == "connect") { + // if (in_connect_mode) { + // std::cout << "Already in connect mode." << std::endl; + // continue; + // } + // in_connect_mode = true; // 进入连接模式 + // std::cout << "Enter the gateway IP address: "; + // std::cin >> ip; + // std::cout << "Enter the gateway port: "; + // std::cin >> port; + // ConnectToGateway(ip, port); + // } else if (command == "exit") { + // exit_flag = true; // 设置退出标志 + // std::cout << "Exiting program." << std::endl; + // // 关闭所有套接字 + // for (auto& sock_pair : sockets) { + // shutdown(sock_pair.first, SHUT_RDWR); // 关闭套接字的发送和接收 + // close(sock_pair.first); + // } + // sockets.clear(); + // std::cout << "sockets.clear" << std::endl; + // // 等待所有线程结束 + // for (auto& thread : threads) { + // if (thread.joinable()) { + // thread.join(); + // } + // } + // threads.clear(); + // break; // 退出主循环 + // } else { + // std::cout << "Unknown command" << std::endl; + // } + // } + // } + // std::cout<<"out"<> command; + + if (command == "connect") { + if (in_connect_mode) { + std::cout << "Already in connect mode." << std::endl; + continue; + } + in_connect_mode = true; + std::cout << "Enter the gateway IP address: "; + std::cin >> ip; + std::cout << "Enter the gateway port: "; + std::cin >> port; + ConnectToGateway(ip, port); + } else if (command == "exit") { + break; // 接收到退出命令,退出主循环 + } else { + std::cout << "Unknown command" << std::endl; + } + } + + // 设置退出标志 + exit_flag = true; + + // 强制结束HTTP服务器线程 + if (http_server_thread.joinable()) { + http_server_thread.join(); + } + + // 关闭所有套接字 + for (auto& sock_pair : sockets) { + shutdown(sock_pair.first, SHUT_RDWR); + close(sock_pair.first); + } + sockets.clear(); + + // 等待所有工作线程结束 + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); + } + } + threads.clear(); + + std::cout << "Exited program." << std::endl; + return 0; + +} \ No newline at end of file diff --git a/src/controller-v1.1/epollip/connector_database.cpp b/src/controller-v1.1/epollip/connector_database.cpp new file mode 100644 index 0000000..d0768cc --- /dev/null +++ b/src/controller-v1.1/epollip/connector_database.cpp @@ -0,0 +1,31 @@ +#include +#include + +int main() { + MYSQL *conn; + conn = mysql_init(NULL); + + if (conn == NULL) { + std::cerr << "MySQL init failed" << std::endl; + return 1; + } + + const char *server = "localhost"; + const char *user = "rtsw"; + const char *password = "123456"; + const char *database = "nginxdb"; + unsigned int port = 3306; // 使用云数据库提供的端口 + + if (mysql_real_connect(conn, server, user, password, database, port, NULL, 0) == NULL) { + std::cerr << "Connection error: " << mysql_error(conn) << std::endl; + mysql_close(conn); + return 1; + } + + std::cout << "Successfully connected to the database" << std::endl; + + // ... 执行数据库操作 ... + + mysql_close(conn); + return 0; +} \ No newline at end of file diff --git a/src/controller-v1.1/epollip/connector_gateway.cpp b/src/controller-v1.1/epollip/connector_gateway.cpp new file mode 100644 index 0000000..b6ba4d7 --- /dev/null +++ b/src/controller-v1.1/epollip/connector_gateway.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include + +#define PORT 8080 +#define MAX_CLIENTS 5 +#define BUFFER_SIZE 1024 + +// 声明 handle_client 函数 +void handle_client(int client_socket); + +int main() { + int server_fd, new_socket; + struct sockaddr_in server_addr, client_addr; + socklen_t client_len = sizeof(client_addr); + char buffer[BUFFER_SIZE]; + int opt = 1; + + // 创建套接字 + server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + perror("socket creation failed"); + exit(EXIT_FAILURE); + } + + // 设置选项,允许重用地址 + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("setsockopt failed"); + exit(EXIT_FAILURE); + } + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(PORT); + + // 绑定 + if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("bind failed"); + exit(EXIT_FAILURE); + } + + // 监听 + if (listen(server_fd, MAX_CLIENTS) < 0) { + perror("listen failed"); + exit(EXIT_FAILURE); + } + + std::cout << "Server listening on port " << PORT << std::endl; + + while (true) { + client_len = sizeof(client_addr); + new_socket = accept(server_fd, (struct sockaddr *)&client_addr, &client_len); + if (new_socket < 0) { + perror("accept failed"); + exit(EXIT_FAILURE); + } + + std::cout << "New client connected from " << inet_ntoa(client_addr.sin_addr) << " port " << ntohs(client_addr.sin_port) << std::endl; + + // 创建并启动线程处理客户端 + std::thread(handle_client, new_socket).detach(); + } + + close(server_fd); + return 0; +} + +// 定义 handle_client 函数 +void handle_client(int client_socket) { + while (true) { + char buffer[BUFFER_SIZE]; + memset(buffer, 0, BUFFER_SIZE); // 清空缓冲区 + int nbytes = read(client_socket, buffer, BUFFER_SIZE); + if (nbytes <= 0) { + std::cout << "Client disconnected." << std::endl; + close(client_socket); + break; + } + std::cout << "Received message from client: " << buffer << std::endl; + // 这里可以添加更多的处理逻辑 + } +} \ No newline at end of file diff --git a/src/controller-v1.1/epollip/db_processer/basic_db.cpp b/src/controller-v1.1/epollip/db_processer/basic_db.cpp new file mode 100644 index 0000000..0abc9ed --- /dev/null +++ b/src/controller-v1.1/epollip/db_processer/basic_db.cpp @@ -0,0 +1,66 @@ +#include +#include + +int main() { + MYSQL *conn; + conn = mysql_init(NULL); + + if (conn == NULL) { + std::cerr << "MySQL init failed" << std::endl; + return 1; + } + + const char *server = "localhost"; + const char *user = "rtsw"; + const char *password = "123456"; + const char *database = "nginxdb"; + unsigned int port = 3306; + + if (mysql_real_connect(conn, server, user, password, database, port, NULL, 0) == NULL) { + std::cerr << "Connection error: " << mysql_error(conn) << std::endl; + mysql_close(conn); + return 1; + } + + std::cout << "Successfully connected to the database" << std::endl; + + // 插入数据 + const char *insert_query = "INSERT INTO users (username, email) VALUES ('newuser', 'newuser@example.com')"; + if (mysql_query(conn, insert_query)) { + std::cerr << "Insert error: " << mysql_error(conn) << std::endl; + } else { + std::cout << "Insert successful" << std::endl; + } + + // 查询数据 + const char *select_query = "SELECT * FROM users"; + MYSQL_RES *result = mysql_store_result(conn); + if (result) { + MYSQL_ROW row; + while ((row = mysql_fetch_row(result))) { + std::cout << "id: " << row[0] << ", username: " << row[1] << ", email: " << row[2] << std::endl; + } + mysql_free_result(result); + } else { + std::cerr << "Select error: " << mysql_error(conn) << std::endl; + } + + // 更新数据 + const char *update_query = "UPDATE users SET email = 'newuser_updated@example.com' WHERE username = 'newuser'"; + if (mysql_query(conn, update_query)) { + std::cerr << "Update error: " << mysql_error(conn) << std::endl; + } else { + std::cout << "Update successful" << std::endl; + } + + // 删除数据 + const char *delete_query = "DELETE FROM users WHERE username = 'newuser'"; + if (mysql_query(conn, delete_query)) { + std::cerr << "Delete error: " << mysql_error(conn) << std::endl; + } else { + std::cout << "Delete successful" << std::endl; + } + + mysql_close(conn); + return 0; +} \ No newline at end of file diff --git a/src/controller-v1.1/epollip/interface/connector_controller.cpp b/src/controller-v1.1/epollip/interface/connector_controller.cpp new file mode 100644 index 0000000..2c93baf --- /dev/null +++ b/src/controller-v1.1/epollip/interface/connector_controller.cpp @@ -0,0 +1,280 @@ +#include "connector_controller.h" + +#define BUFFER_SIZE 1024 +#define HTTP_SERVER_PORT 8080 + +std::vector threads; // 存储所有连接线程 +std::map sockets; // 存储套接字 +std::mutex sockets_mutex; // 用于同步访问 sockets +std::atomic exit_flag(false); // 原子退出标志 + + +// 维护连接的函数 +void KeepConnection(int sock) { + char buffer[BUFFER_SIZE]; + int nbytes; + while (!exit_flag) { + nbytes = recv(sock, buffer, BUFFER_SIZE, 0); + if (nbytes <= 0) { + std::cout << "Gateway disconnected" << std::endl; + break; + } + std::cout << "Received from gateway (Socket " << sock << "): " << buffer << std::endl; + } + + { + std::lock_guard lock(sockets_mutex); + sockets.erase(sock); // 从集合中移除套接字 + } + close(sock); +} +// 连接到网关的函数 +void ConnectToGateway(const std::string& ip, int port) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("Could not create socket"); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) { + perror("Invalid address"); + close(sock); + return; + } + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Connection to the server failed"); + close(sock); + return; + } + + { + std::lock_guard lock(sockets_mutex); + sockets[sock] = 1; // 将套接字添加到集合中 + } + + std::cout << "Connected to gateway at " << ip << ":" << port << " (Socket " << sock << ")" << std::endl; + + // 在新线程中维护连接 + threads.emplace_back(KeepConnection, sock); +} + +// 处理HTTP请求的函数 +void HandleHttpRequest(int client_socket) { + char buffer[BUFFER_SIZE]; + int bytes_read = recv(client_socket, buffer, sizeof(buffer), 0); + if (bytes_read <= 0) { + close(client_socket); + return; + } + + // 简单解析HTTP请求 + std::string http_request(buffer, bytes_read); + std::string ip; + int port; + + // 寻找IP和端口号 + auto host_pos = http_request.find("Host: "); + if (host_pos != std::string::npos) { + auto start = host_pos + std::string("Host: ").size(); + ip = http_request.substr(start, http_request.find("\r\n", start) - start); + } + + auto content_length_pos = http_request.find("Content-Length:"); + if (content_length_pos != std::string::npos) { + auto start = content_length_pos + std::string("Content-Length: ").size(); + int length = std::stoi(http_request.substr(start, http_request.find("\r\n", start) - start)); + if (length > 0) { + char* content = new char[length]; + bytes_read = recv(client_socket, content, length, 0); + if (bytes_read > 0) { + // 解析JSON内容(假设前端发送的是JSON格式) + // 这里需要添加JSON解析逻辑来提取IP和端口 + // 示例:{"ip":"192.168.1.1","port":8080} + // 可以使用第三方库如nlohmann/json来解析JSON + + // 假设解析后得到ip和port + // ConnectToGateway(ip, port); + + delete[] content; + } + } + } + + // 发送HTTP响应 + std::string response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; + send(client_socket, response.c_str(), response.size(), 0); + close(client_socket); +} + +// 启动HTTP服务器的函数 +void StartHttpServer() { + int http_server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (http_server_socket < 0) { + perror("Could not create HTTP server socket"); + return; + } + + int opt = 1; + if (setsockopt(http_server_socket, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("Setsockopt failed"); + close(http_server_socket); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(HTTP_SERVER_PORT); + + if (bind(http_server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Bind failed"); + close(http_server_socket); + return; + } + + if (listen(http_server_socket, 5) < 0) { + perror("Listen failed"); + close(http_server_socket); + return; + } + + std::cout << "HTTP server listening on port " << HTTP_SERVER_PORT << std::endl; + + while (!exit_flag) { + int client_socket = accept(http_server_socket, NULL, NULL); + if (client_socket < 0) { + perror("Accept failed"); + continue; + } + + threads.emplace_back(HandleHttpRequest, client_socket); + } + + close(http_server_socket); +} + +/* +int main() { + // threads.emplace_back(StartHttpServer); + + // std::string command, ip; + // int port; + // bool in_connect_mode = false; + // std::cout << "Enter command (connect/exit): "; + // while (true) { + + // if (in_connect_mode) + // { + // std::cout << "continue connect or not ? (y or n) "; + // std::cin >> command; + // if(command=="y"){ + // std::cout << "Enter the gateway IP address: "; + // std::cin >> ip; + // std::cout << "Enter the gateway port: "; + // std::cin >> port; + // ConnectToGateway(ip, port); + // } + // else { + // in_connect_mode = false; // 退出连接模式 + // std::cout << "Exiting connect mode." << std::endl; + // } + // } + // else{ + // std::cout << "Enter command (connect/exit): "; + // std::cin>>command; + // if (command == "connect") { + // if (in_connect_mode) { + // std::cout << "Already in connect mode." << std::endl; + // continue; + // } + // in_connect_mode = true; // 进入连接模式 + // std::cout << "Enter the gateway IP address: "; + // std::cin >> ip; + // std::cout << "Enter the gateway port: "; + // std::cin >> port; + // ConnectToGateway(ip, port); + // } else if (command == "exit") { + // exit_flag = true; // 设置退出标志 + // std::cout << "Exiting program." << std::endl; + // // 关闭所有套接字 + // for (auto& sock_pair : sockets) { + // shutdown(sock_pair.first, SHUT_RDWR); // 关闭套接字的发送和接收 + // close(sock_pair.first); + // } + // sockets.clear(); + // std::cout << "sockets.clear" << std::endl; + // // 等待所有线程结束 + // for (auto& thread : threads) { + // if (thread.joinable()) { + // thread.join(); + // } + // } + // threads.clear(); + // break; // 退出主循环 + // } else { + // std::cout << "Unknown command" << std::endl; + // } + // } + // } + // std::cout<<"out"<> command; + + if (command == "connect") { + if (in_connect_mode) { + std::cout << "Already in connect mode." << std::endl; + continue; + } + in_connect_mode = true; + std::cout << "Enter the gateway IP address: "; + std::cin >> ip; + std::cout << "Enter the gateway port: "; + std::cin >> port; + ConnectToGateway(ip, port); + } else if (command == "exit") { + break; // 接收到退出命令,退出主循环 + } else { + std::cout << "Unknown command" << std::endl; + } + } + + // 设置退出标志 + exit_flag = true; + + // 强制结束HTTP服务器线程 + if (http_server_thread.joinable()) { + http_server_thread.join(); + } + + // 关闭所有套接字 + for (auto& sock_pair : sockets) { + shutdown(sock_pair.first, SHUT_RDWR); + close(sock_pair.first); + } + sockets.clear(); + + // 等待所有工作线程结束 + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); + } + } + threads.clear(); + + std::cout << "Exited program." << std::endl; + return 0; + +} +*/ \ No newline at end of file diff --git a/src/controller-v1.1/epollip/interface/connector_controller.h b/src/controller-v1.1/epollip/interface/connector_controller.h new file mode 100644 index 0000000..c45ca15 --- /dev/null +++ b/src/controller-v1.1/epollip/interface/connector_controller.h @@ -0,0 +1,22 @@ +#ifndef CONNECTOR_CONTROLLER_H +#define CONNECTOR_CONTROLLER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 函数声明 +void StartHttpServer(); +void ConnectToGateway(const std::string& ip, int port); +void KeepConnection(int sock); +void HandleHttpRequest(int client_socket); + +#endif // CONNECTOR_CONTROLLER_H \ No newline at end of file diff --git a/src/controller-v1.1/epollip/interface/connector_database.cpp b/src/controller-v1.1/epollip/interface/connector_database.cpp new file mode 100644 index 0000000..212bfd5 --- /dev/null +++ b/src/controller-v1.1/epollip/interface/connector_database.cpp @@ -0,0 +1,68 @@ +/* + 这个文件可以只负责链接数据库,其他的都不管 + 把数据库的句柄传给主程序 +*/ + +/* +#include +#include + +int main() { + MYSQL *conn; + conn = mysql_init(NULL); + + if (conn == NULL) { + std::cerr << "MySQL init failed" << std::endl; + return 1; + } + + const char *server = "localhost"; + const char *user = "rtsw"; + const char *password = "123456"; + const char *database = "nginxdb"; + unsigned int port = 3306; // 使用云数据库提供的端口 + + if (mysql_real_connect(conn, server, user, password, database, port, NULL, 0) == NULL) { + std::cerr << "Connection error: " << mysql_error(conn) << std::endl; + mysql_close(conn); + return 1; + } + + std::cout << "Successfully connected to the database" << std::endl; + + // ... 执行数据库操作 ... + + mysql_close(conn); + return 0; +} +*/ + +#include "connector_database.h" + +// DatabaseOperation函数定义 +void DatabaseOperation() { + MYSQL *conn = mysql_init(NULL); + + if (conn == NULL) { + std::cerr << "MySQL init failed" << std::endl; + return; + } + + const char *server = "localhost"; + const char *user = "rtsw"; + const char *password = "123456"; + const char *database = "nginxdb"; + unsigned int port = 3306; + + if (mysql_real_connect(conn, server, user, password, database, port, NULL, 0) == NULL) { + std::cerr << "Connection error: " << mysql_error(conn) << std::endl; + mysql_close(conn); + return; + } + + std::cout << "Successfully connected to the database" << std::endl; + + // ... 执行数据库操作 ... + + mysql_close(conn); +} \ No newline at end of file diff --git a/src/controller-v1.1/epollip/interface/connector_database.h b/src/controller-v1.1/epollip/interface/connector_database.h new file mode 100644 index 0000000..83a2cf6 --- /dev/null +++ b/src/controller-v1.1/epollip/interface/connector_database.h @@ -0,0 +1,10 @@ +#ifndef CONNECTOR_DATABASE_H +#define CONNECTOR_DATABASE_H + +#include +#include + +// 函数声明 +void DatabaseOperation(); + +#endif // CONNECTOR_DATABASE_H \ No newline at end of file diff --git a/src/controller-v1.1/epollip/interface/main.cpp b/src/controller-v1.1/epollip/interface/main.cpp new file mode 100644 index 0000000..e469900 --- /dev/null +++ b/src/controller-v1.1/epollip/interface/main.cpp @@ -0,0 +1,35 @@ +#include +#include +#include "connector_controller.h" +#include "connector_database.h" + +int main() { + std::string command; + bool running = true; + + while (running) { + std::cout << "Enter command (start_http_server/connect_gateway/database_operation/exit): "; + std::cin >> command; + + if (command == "start_http_server") { + StartHttpServer(); + } else if (command == "connect_gateway") { + std::string ip; + int port; + std::cout << "Enter the gateway IP address: "<>ip; // 使用getline以获取包含空格的IP地址 + std::cout << "Enter the gateway port: "<> port; + ConnectToGateway(ip, port); + } else if (command == "database_operation") { + DatabaseOperation(); + } else if (command == "exit") { + running = false; + } else { + std::cout << "Unknown command" << std::endl; + } + } + + std::cout << "Exiting program." << std::endl; + return 0; +} \ No newline at end of file diff --git a/src/controller-v1.1/epollip/interface/main_program b/src/controller-v1.1/epollip/interface/main_program new file mode 100644 index 0000000000000000000000000000000000000000..71bad27e38cebcd16ab3583728dd749c317ac390 GIT binary patch literal 90968 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 1024 + +std::vector threads; // 存储所有连接线程 +std::map sockets; // 存储套接字 +std::mutex sockets_mutex; // 用于同步访问 sockets +std::atomic exit_flag(false); // 原子退出标志 + + +// 维护连接的函数 +void KeepConnection(int sock) { + char buffer[BUFFER_SIZE]; + int nbytes; + while (!exit_flag) { + nbytes = recv(sock, buffer, BUFFER_SIZE, 0); + if (nbytes <= 0) { + std::cout << "Gateway disconnected" << std::endl; + break; + } + std::cout << "Received from gateway (Socket " << sock << "): " << buffer << std::endl; + } + + { + std::lock_guard lock(sockets_mutex); + sockets.erase(sock); // 从集合中移除套接字 + } + close(sock); +} +// 连接到网关的函数 +void ConnectToGateway(const std::string& ip, int port) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("Could not create socket"); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) { + perror("Invalid address"); + close(sock); + return; + } + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Connection to the server failed"); + close(sock); + return; + } + + { + std::lock_guard lock(sockets_mutex); + sockets[sock] = 1; // 将套接字添加到集合中 + } + + std::cout << "Connected to gateway at " << ip << ":" << port << " (Socket " << sock << ")" << std::endl; + + // 在新线程中维护连接 + threads.emplace_back(KeepConnection, sock); +} + + + +int main() { + std::string command, ip; + int port; + bool in_connect_mode = false; + + while (true) { + std::cout << "Enter command (connect/exitconnect/exit): "; + std::cin >> command; + + if (command == "connect") { + if (in_connect_mode) { + std::cout << "Already in connect mode." << std::endl; + continue; + } + in_connect_mode = true; // 进入连接模式 + std::cout << "Enter the gateway IP address: "; + std::cin >> ip; + std::cout << "Enter the gateway port: "; + std::cin >> port; + ConnectToGateway(ip, port); + } else if (command == "exitconnect") { + if (!in_connect_mode) { + std::cout << "Not in connect mode." << std::endl; + continue; + } + in_connect_mode = false; // 退出连接模式 + std::cout << "Exiting connect mode." << std::endl; + } else if (command == "exit") { + exit_flag = true; // 设置退出标志 + std::cout << "Exiting program." << std::endl; + // 关闭所有套接字 + for (auto& sock_pair : sockets) { + shutdown(sock_pair.first, SHUT_RDWR); // 关闭套接字的发送和接收 + close(sock_pair.first); + } + sockets.clear(); + // 等待所有线程结束 + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); + } + } + threads.clear(); + break; // 退出主循环 + } else { + std::cout << "Unknown command" << std::endl; + } + } + + return 0; +} \ No newline at end of file diff --git a/src/controller/connector_controller.cpp b/src/controller/connector_controller.cpp new file mode 100644 index 0000000..6b0d54c --- /dev/null +++ b/src/controller/connector_controller.cpp @@ -0,0 +1,288 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 1024 +#define HTTP_SERVER_PORT 8080 + +std::vector threads; // 存储所有连接线程 +std::map sockets; // 存储套接字 +std::mutex sockets_mutex; // 用于同步访问 sockets +std::atomic exit_flag(false); // 原子退出标志 + + +// 维护连接的函数 +void KeepConnection(int sock) { + char buffer[BUFFER_SIZE]; + int nbytes; + while (!exit_flag) { + nbytes = recv(sock, buffer, BUFFER_SIZE, 0); + if (nbytes <= 0) { + std::cout << "Gateway disconnected" << std::endl; + break; + } + std::cout << "Received from gateway (Socket " << sock << "): " << buffer << std::endl; + } + + { + std::lock_guard lock(sockets_mutex); + sockets.erase(sock); // 从集合中移除套接字 + } + close(sock); +} +// 连接到网关的函数 +void ConnectToGateway(const std::string& ip, int port) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("Could not create socket"); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) { + perror("Invalid address"); + close(sock); + return; + } + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Connection to the server failed"); + close(sock); + return; + } + + { + std::lock_guard lock(sockets_mutex); + sockets[sock] = 1; // 将套接字添加到集合中 + } + + std::cout << "Connected to gateway at " << ip << ":" << port << " (Socket " << sock << ")" << std::endl; + + // 在新线程中维护连接 + threads.emplace_back(KeepConnection, sock); +} + +// 处理HTTP请求的函数 +void HandleHttpRequest(int client_socket) { + char buffer[BUFFER_SIZE]; + int bytes_read = recv(client_socket, buffer, sizeof(buffer), 0); + if (bytes_read <= 0) { + close(client_socket); + return; + } + + // 简单解析HTTP请求 + std::string http_request(buffer, bytes_read); + std::string ip; + int port; + + // 寻找IP和端口号 + auto host_pos = http_request.find("Host: "); + if (host_pos != std::string::npos) { + auto start = host_pos + std::string("Host: ").size(); + ip = http_request.substr(start, http_request.find("\r\n", start) - start); + } + + auto content_length_pos = http_request.find("Content-Length:"); + if (content_length_pos != std::string::npos) { + auto start = content_length_pos + std::string("Content-Length: ").size(); + int length = std::stoi(http_request.substr(start, http_request.find("\r\n", start) - start)); + if (length > 0) { + char* content = new char[length]; + bytes_read = recv(client_socket, content, length, 0); + if (bytes_read > 0) { + // 解析JSON内容(假设前端发送的是JSON格式) + // 这里需要添加JSON解析逻辑来提取IP和端口 + // 示例:{"ip":"192.168.1.1","port":8080} + // 可以使用第三方库如nlohmann/json来解析JSON + + // 假设解析后得到ip和port + // ConnectToGateway(ip, port); + + delete[] content; + } + } + } + + // 发送HTTP响应 + std::string response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; + send(client_socket, response.c_str(), response.size(), 0); + close(client_socket); +} + +// 启动HTTP服务器的函数 +void StartHttpServer() { + int http_server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (http_server_socket < 0) { + perror("Could not create HTTP server socket"); + return; + } + + int opt = 1; + if (setsockopt(http_server_socket, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("Setsockopt failed"); + close(http_server_socket); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(HTTP_SERVER_PORT); + + if (bind(http_server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Bind failed"); + close(http_server_socket); + return; + } + + if (listen(http_server_socket, 5) < 0) { + perror("Listen failed"); + close(http_server_socket); + return; + } + + std::cout << "HTTP server listening on port " << HTTP_SERVER_PORT << std::endl; + + while (!exit_flag) { + int client_socket = accept(http_server_socket, NULL, NULL); + if (client_socket < 0) { + perror("Accept failed"); + continue; + } + + threads.emplace_back(HandleHttpRequest, client_socket); + } + + close(http_server_socket); +} + +int main() { + // threads.emplace_back(StartHttpServer); + + // std::string command, ip; + // int port; + // bool in_connect_mode = false; + // std::cout << "Enter command (connect/exit): "; + // while (true) { + + // if (in_connect_mode) + // { + // std::cout << "continue connect or not ? (y or n) "; + // std::cin >> command; + // if(command=="y"){ + // std::cout << "Enter the gateway IP address: "; + // std::cin >> ip; + // std::cout << "Enter the gateway port: "; + // std::cin >> port; + // ConnectToGateway(ip, port); + // } + // else { + // in_connect_mode = false; // 退出连接模式 + // std::cout << "Exiting connect mode." << std::endl; + // } + // } + // else{ + // std::cout << "Enter command (connect/exit): "; + // std::cin>>command; + // if (command == "connect") { + // if (in_connect_mode) { + // std::cout << "Already in connect mode." << std::endl; + // continue; + // } + // in_connect_mode = true; // 进入连接模式 + // std::cout << "Enter the gateway IP address: "; + // std::cin >> ip; + // std::cout << "Enter the gateway port: "; + // std::cin >> port; + // ConnectToGateway(ip, port); + // } else if (command == "exit") { + // exit_flag = true; // 设置退出标志 + // std::cout << "Exiting program." << std::endl; + // // 关闭所有套接字 + // for (auto& sock_pair : sockets) { + // shutdown(sock_pair.first, SHUT_RDWR); // 关闭套接字的发送和接收 + // close(sock_pair.first); + // } + // sockets.clear(); + // std::cout << "sockets.clear" << std::endl; + // // 等待所有线程结束 + // for (auto& thread : threads) { + // if (thread.joinable()) { + // thread.join(); + // } + // } + // threads.clear(); + // break; // 退出主循环 + // } else { + // std::cout << "Unknown command" << std::endl; + // } + // } + // } + // std::cout<<"out"<> command; + + if (command == "connect") { + if (in_connect_mode) { + std::cout << "Already in connect mode." << std::endl; + continue; + } + in_connect_mode = true; + std::cout << "Enter the gateway IP address: "; + std::cin >> ip; + std::cout << "Enter the gateway port: "; + std::cin >> port; + ConnectToGateway(ip, port); + } else if (command == "exit") { + break; // 接收到退出命令,退出主循环 + } else { + std::cout << "Unknown command" << std::endl; + } + } + + // 设置退出标志 + exit_flag = true; + + // 强制结束HTTP服务器线程 + if (http_server_thread.joinable()) { + http_server_thread.join(); + } + + // 关闭所有套接字 + for (auto& sock_pair : sockets) { + shutdown(sock_pair.first, SHUT_RDWR); + close(sock_pair.first); + } + sockets.clear(); + + // 等待所有工作线程结束 + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); + } + } + threads.clear(); + + std::cout << "Exited program." << std::endl; + return 0; + +} \ No newline at end of file diff --git a/src/controller/connector_database.cpp b/src/controller/connector_database.cpp new file mode 100644 index 0000000..d0768cc --- /dev/null +++ b/src/controller/connector_database.cpp @@ -0,0 +1,31 @@ +#include +#include + +int main() { + MYSQL *conn; + conn = mysql_init(NULL); + + if (conn == NULL) { + std::cerr << "MySQL init failed" << std::endl; + return 1; + } + + const char *server = "localhost"; + const char *user = "rtsw"; + const char *password = "123456"; + const char *database = "nginxdb"; + unsigned int port = 3306; // 使用云数据库提供的端口 + + if (mysql_real_connect(conn, server, user, password, database, port, NULL, 0) == NULL) { + std::cerr << "Connection error: " << mysql_error(conn) << std::endl; + mysql_close(conn); + return 1; + } + + std::cout << "Successfully connected to the database" << std::endl; + + // ... 执行数据库操作 ... + + mysql_close(conn); + return 0; +} \ No newline at end of file diff --git a/src/controller/connector_gateway.cpp b/src/controller/connector_gateway.cpp new file mode 100644 index 0000000..b6ba4d7 --- /dev/null +++ b/src/controller/connector_gateway.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include + +#define PORT 8080 +#define MAX_CLIENTS 5 +#define BUFFER_SIZE 1024 + +// 声明 handle_client 函数 +void handle_client(int client_socket); + +int main() { + int server_fd, new_socket; + struct sockaddr_in server_addr, client_addr; + socklen_t client_len = sizeof(client_addr); + char buffer[BUFFER_SIZE]; + int opt = 1; + + // 创建套接字 + server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + perror("socket creation failed"); + exit(EXIT_FAILURE); + } + + // 设置选项,允许重用地址 + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("setsockopt failed"); + exit(EXIT_FAILURE); + } + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(PORT); + + // 绑定 + if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("bind failed"); + exit(EXIT_FAILURE); + } + + // 监听 + if (listen(server_fd, MAX_CLIENTS) < 0) { + perror("listen failed"); + exit(EXIT_FAILURE); + } + + std::cout << "Server listening on port " << PORT << std::endl; + + while (true) { + client_len = sizeof(client_addr); + new_socket = accept(server_fd, (struct sockaddr *)&client_addr, &client_len); + if (new_socket < 0) { + perror("accept failed"); + exit(EXIT_FAILURE); + } + + std::cout << "New client connected from " << inet_ntoa(client_addr.sin_addr) << " port " << ntohs(client_addr.sin_port) << std::endl; + + // 创建并启动线程处理客户端 + std::thread(handle_client, new_socket).detach(); + } + + close(server_fd); + return 0; +} + +// 定义 handle_client 函数 +void handle_client(int client_socket) { + while (true) { + char buffer[BUFFER_SIZE]; + memset(buffer, 0, BUFFER_SIZE); // 清空缓冲区 + int nbytes = read(client_socket, buffer, BUFFER_SIZE); + if (nbytes <= 0) { + std::cout << "Client disconnected." << std::endl; + close(client_socket); + break; + } + std::cout << "Received message from client: " << buffer << std::endl; + // 这里可以添加更多的处理逻辑 + } +} \ No newline at end of file diff --git a/src/controller/db_processer/basic_db.cpp b/src/controller/db_processer/basic_db.cpp new file mode 100644 index 0000000..0abc9ed --- /dev/null +++ b/src/controller/db_processer/basic_db.cpp @@ -0,0 +1,66 @@ +#include +#include + +int main() { + MYSQL *conn; + conn = mysql_init(NULL); + + if (conn == NULL) { + std::cerr << "MySQL init failed" << std::endl; + return 1; + } + + const char *server = "localhost"; + const char *user = "rtsw"; + const char *password = "123456"; + const char *database = "nginxdb"; + unsigned int port = 3306; + + if (mysql_real_connect(conn, server, user, password, database, port, NULL, 0) == NULL) { + std::cerr << "Connection error: " << mysql_error(conn) << std::endl; + mysql_close(conn); + return 1; + } + + std::cout << "Successfully connected to the database" << std::endl; + + // 插入数据 + const char *insert_query = "INSERT INTO users (username, email) VALUES ('newuser', 'newuser@example.com')"; + if (mysql_query(conn, insert_query)) { + std::cerr << "Insert error: " << mysql_error(conn) << std::endl; + } else { + std::cout << "Insert successful" << std::endl; + } + + // 查询数据 + const char *select_query = "SELECT * FROM users"; + MYSQL_RES *result = mysql_store_result(conn); + if (result) { + MYSQL_ROW row; + while ((row = mysql_fetch_row(result))) { + std::cout << "id: " << row[0] << ", username: " << row[1] << ", email: " << row[2] << std::endl; + } + mysql_free_result(result); + } else { + std::cerr << "Select error: " << mysql_error(conn) << std::endl; + } + + // 更新数据 + const char *update_query = "UPDATE users SET email = 'newuser_updated@example.com' WHERE username = 'newuser'"; + if (mysql_query(conn, update_query)) { + std::cerr << "Update error: " << mysql_error(conn) << std::endl; + } else { + std::cout << "Update successful" << std::endl; + } + + // 删除数据 + const char *delete_query = "DELETE FROM users WHERE username = 'newuser'"; + if (mysql_query(conn, delete_query)) { + std::cerr << "Delete error: " << mysql_error(conn) << std::endl; + } else { + std::cout << "Delete successful" << std::endl; + } + + mysql_close(conn); + return 0; +} \ No newline at end of file diff --git a/src/controller/interface/connector_controller.cpp b/src/controller/interface/connector_controller.cpp new file mode 100644 index 0000000..2c93baf --- /dev/null +++ b/src/controller/interface/connector_controller.cpp @@ -0,0 +1,280 @@ +#include "connector_controller.h" + +#define BUFFER_SIZE 1024 +#define HTTP_SERVER_PORT 8080 + +std::vector threads; // 存储所有连接线程 +std::map sockets; // 存储套接字 +std::mutex sockets_mutex; // 用于同步访问 sockets +std::atomic exit_flag(false); // 原子退出标志 + + +// 维护连接的函数 +void KeepConnection(int sock) { + char buffer[BUFFER_SIZE]; + int nbytes; + while (!exit_flag) { + nbytes = recv(sock, buffer, BUFFER_SIZE, 0); + if (nbytes <= 0) { + std::cout << "Gateway disconnected" << std::endl; + break; + } + std::cout << "Received from gateway (Socket " << sock << "): " << buffer << std::endl; + } + + { + std::lock_guard lock(sockets_mutex); + sockets.erase(sock); // 从集合中移除套接字 + } + close(sock); +} +// 连接到网关的函数 +void ConnectToGateway(const std::string& ip, int port) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("Could not create socket"); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) { + perror("Invalid address"); + close(sock); + return; + } + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Connection to the server failed"); + close(sock); + return; + } + + { + std::lock_guard lock(sockets_mutex); + sockets[sock] = 1; // 将套接字添加到集合中 + } + + std::cout << "Connected to gateway at " << ip << ":" << port << " (Socket " << sock << ")" << std::endl; + + // 在新线程中维护连接 + threads.emplace_back(KeepConnection, sock); +} + +// 处理HTTP请求的函数 +void HandleHttpRequest(int client_socket) { + char buffer[BUFFER_SIZE]; + int bytes_read = recv(client_socket, buffer, sizeof(buffer), 0); + if (bytes_read <= 0) { + close(client_socket); + return; + } + + // 简单解析HTTP请求 + std::string http_request(buffer, bytes_read); + std::string ip; + int port; + + // 寻找IP和端口号 + auto host_pos = http_request.find("Host: "); + if (host_pos != std::string::npos) { + auto start = host_pos + std::string("Host: ").size(); + ip = http_request.substr(start, http_request.find("\r\n", start) - start); + } + + auto content_length_pos = http_request.find("Content-Length:"); + if (content_length_pos != std::string::npos) { + auto start = content_length_pos + std::string("Content-Length: ").size(); + int length = std::stoi(http_request.substr(start, http_request.find("\r\n", start) - start)); + if (length > 0) { + char* content = new char[length]; + bytes_read = recv(client_socket, content, length, 0); + if (bytes_read > 0) { + // 解析JSON内容(假设前端发送的是JSON格式) + // 这里需要添加JSON解析逻辑来提取IP和端口 + // 示例:{"ip":"192.168.1.1","port":8080} + // 可以使用第三方库如nlohmann/json来解析JSON + + // 假设解析后得到ip和port + // ConnectToGateway(ip, port); + + delete[] content; + } + } + } + + // 发送HTTP响应 + std::string response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; + send(client_socket, response.c_str(), response.size(), 0); + close(client_socket); +} + +// 启动HTTP服务器的函数 +void StartHttpServer() { + int http_server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (http_server_socket < 0) { + perror("Could not create HTTP server socket"); + return; + } + + int opt = 1; + if (setsockopt(http_server_socket, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("Setsockopt failed"); + close(http_server_socket); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(HTTP_SERVER_PORT); + + if (bind(http_server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Bind failed"); + close(http_server_socket); + return; + } + + if (listen(http_server_socket, 5) < 0) { + perror("Listen failed"); + close(http_server_socket); + return; + } + + std::cout << "HTTP server listening on port " << HTTP_SERVER_PORT << std::endl; + + while (!exit_flag) { + int client_socket = accept(http_server_socket, NULL, NULL); + if (client_socket < 0) { + perror("Accept failed"); + continue; + } + + threads.emplace_back(HandleHttpRequest, client_socket); + } + + close(http_server_socket); +} + +/* +int main() { + // threads.emplace_back(StartHttpServer); + + // std::string command, ip; + // int port; + // bool in_connect_mode = false; + // std::cout << "Enter command (connect/exit): "; + // while (true) { + + // if (in_connect_mode) + // { + // std::cout << "continue connect or not ? (y or n) "; + // std::cin >> command; + // if(command=="y"){ + // std::cout << "Enter the gateway IP address: "; + // std::cin >> ip; + // std::cout << "Enter the gateway port: "; + // std::cin >> port; + // ConnectToGateway(ip, port); + // } + // else { + // in_connect_mode = false; // 退出连接模式 + // std::cout << "Exiting connect mode." << std::endl; + // } + // } + // else{ + // std::cout << "Enter command (connect/exit): "; + // std::cin>>command; + // if (command == "connect") { + // if (in_connect_mode) { + // std::cout << "Already in connect mode." << std::endl; + // continue; + // } + // in_connect_mode = true; // 进入连接模式 + // std::cout << "Enter the gateway IP address: "; + // std::cin >> ip; + // std::cout << "Enter the gateway port: "; + // std::cin >> port; + // ConnectToGateway(ip, port); + // } else if (command == "exit") { + // exit_flag = true; // 设置退出标志 + // std::cout << "Exiting program." << std::endl; + // // 关闭所有套接字 + // for (auto& sock_pair : sockets) { + // shutdown(sock_pair.first, SHUT_RDWR); // 关闭套接字的发送和接收 + // close(sock_pair.first); + // } + // sockets.clear(); + // std::cout << "sockets.clear" << std::endl; + // // 等待所有线程结束 + // for (auto& thread : threads) { + // if (thread.joinable()) { + // thread.join(); + // } + // } + // threads.clear(); + // break; // 退出主循环 + // } else { + // std::cout << "Unknown command" << std::endl; + // } + // } + // } + // std::cout<<"out"<> command; + + if (command == "connect") { + if (in_connect_mode) { + std::cout << "Already in connect mode." << std::endl; + continue; + } + in_connect_mode = true; + std::cout << "Enter the gateway IP address: "; + std::cin >> ip; + std::cout << "Enter the gateway port: "; + std::cin >> port; + ConnectToGateway(ip, port); + } else if (command == "exit") { + break; // 接收到退出命令,退出主循环 + } else { + std::cout << "Unknown command" << std::endl; + } + } + + // 设置退出标志 + exit_flag = true; + + // 强制结束HTTP服务器线程 + if (http_server_thread.joinable()) { + http_server_thread.join(); + } + + // 关闭所有套接字 + for (auto& sock_pair : sockets) { + shutdown(sock_pair.first, SHUT_RDWR); + close(sock_pair.first); + } + sockets.clear(); + + // 等待所有工作线程结束 + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); + } + } + threads.clear(); + + std::cout << "Exited program." << std::endl; + return 0; + +} +*/ \ No newline at end of file diff --git a/src/controller/interface/connector_controller.h b/src/controller/interface/connector_controller.h new file mode 100644 index 0000000..c45ca15 --- /dev/null +++ b/src/controller/interface/connector_controller.h @@ -0,0 +1,22 @@ +#ifndef CONNECTOR_CONTROLLER_H +#define CONNECTOR_CONTROLLER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 函数声明 +void StartHttpServer(); +void ConnectToGateway(const std::string& ip, int port); +void KeepConnection(int sock); +void HandleHttpRequest(int client_socket); + +#endif // CONNECTOR_CONTROLLER_H \ No newline at end of file diff --git a/src/controller/interface/connector_database.cpp b/src/controller/interface/connector_database.cpp new file mode 100644 index 0000000..212bfd5 --- /dev/null +++ b/src/controller/interface/connector_database.cpp @@ -0,0 +1,68 @@ +/* + 这个文件可以只负责链接数据库,其他的都不管 + 把数据库的句柄传给主程序 +*/ + +/* +#include +#include + +int main() { + MYSQL *conn; + conn = mysql_init(NULL); + + if (conn == NULL) { + std::cerr << "MySQL init failed" << std::endl; + return 1; + } + + const char *server = "localhost"; + const char *user = "rtsw"; + const char *password = "123456"; + const char *database = "nginxdb"; + unsigned int port = 3306; // 使用云数据库提供的端口 + + if (mysql_real_connect(conn, server, user, password, database, port, NULL, 0) == NULL) { + std::cerr << "Connection error: " << mysql_error(conn) << std::endl; + mysql_close(conn); + return 1; + } + + std::cout << "Successfully connected to the database" << std::endl; + + // ... 执行数据库操作 ... + + mysql_close(conn); + return 0; +} +*/ + +#include "connector_database.h" + +// DatabaseOperation函数定义 +void DatabaseOperation() { + MYSQL *conn = mysql_init(NULL); + + if (conn == NULL) { + std::cerr << "MySQL init failed" << std::endl; + return; + } + + const char *server = "localhost"; + const char *user = "rtsw"; + const char *password = "123456"; + const char *database = "nginxdb"; + unsigned int port = 3306; + + if (mysql_real_connect(conn, server, user, password, database, port, NULL, 0) == NULL) { + std::cerr << "Connection error: " << mysql_error(conn) << std::endl; + mysql_close(conn); + return; + } + + std::cout << "Successfully connected to the database" << std::endl; + + // ... 执行数据库操作 ... + + mysql_close(conn); +} \ No newline at end of file diff --git a/src/controller/interface/connector_database.h b/src/controller/interface/connector_database.h new file mode 100644 index 0000000..83a2cf6 --- /dev/null +++ b/src/controller/interface/connector_database.h @@ -0,0 +1,10 @@ +#ifndef CONNECTOR_DATABASE_H +#define CONNECTOR_DATABASE_H + +#include +#include + +// 函数声明 +void DatabaseOperation(); + +#endif // CONNECTOR_DATABASE_H \ No newline at end of file diff --git a/src/controller/interface/main.cpp b/src/controller/interface/main.cpp new file mode 100644 index 0000000..e469900 --- /dev/null +++ b/src/controller/interface/main.cpp @@ -0,0 +1,35 @@ +#include +#include +#include "connector_controller.h" +#include "connector_database.h" + +int main() { + std::string command; + bool running = true; + + while (running) { + std::cout << "Enter command (start_http_server/connect_gateway/database_operation/exit): "; + std::cin >> command; + + if (command == "start_http_server") { + StartHttpServer(); + } else if (command == "connect_gateway") { + std::string ip; + int port; + std::cout << "Enter the gateway IP address: "<>ip; // 使用getline以获取包含空格的IP地址 + std::cout << "Enter the gateway port: "<> port; + ConnectToGateway(ip, port); + } else if (command == "database_operation") { + DatabaseOperation(); + } else if (command == "exit") { + running = false; + } else { + std::cout << "Unknown command" << std::endl; + } + } + + std::cout << "Exiting program." << std::endl; + return 0; +} \ No newline at end of file diff --git a/src/controller/interface/main_program b/src/controller/interface/main_program new file mode 100644 index 0000000000000000000000000000000000000000..71bad27e38cebcd16ab3583728dd749c317ac390 GIT binary patch literal 90968 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 1024 + +std::vector threads; // 存储所有连接线程 +std::map sockets; // 存储套接字 +std::mutex sockets_mutex; // 用于同步访问 sockets +std::atomic exit_flag(false); // 原子退出标志 + + +// 维护连接的函数 +void KeepConnection(int sock) { + char buffer[BUFFER_SIZE]; + int nbytes; + while (!exit_flag) { + nbytes = recv(sock, buffer, BUFFER_SIZE, 0); + if (nbytes <= 0) { + std::cout << "Gateway disconnected" << std::endl; + break; + } + std::cout << "Received from gateway (Socket " << sock << "): " << buffer << std::endl; + } + + { + std::lock_guard lock(sockets_mutex); + sockets.erase(sock); // 从集合中移除套接字 + } + close(sock); +} +// 连接到网关的函数 +void ConnectToGateway(const std::string& ip, int port) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("Could not create socket"); + return; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + if (inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr) <= 0) { + perror("Invalid address"); + close(sock); + return; + } + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("Connection to the server failed"); + close(sock); + return; + } + + { + std::lock_guard lock(sockets_mutex); + sockets[sock] = 1; // 将套接字添加到集合中 + } + + std::cout << "Connected to gateway at " << ip << ":" << port << " (Socket " << sock << ")" << std::endl; + + // 在新线程中维护连接 + threads.emplace_back(KeepConnection, sock); +} + + + +int main() { + std::string command, ip; + int port; + bool in_connect_mode = false; + + while (true) { + std::cout << "Enter command (connect/exitconnect/exit): "; + std::cin >> command; + + if (command == "connect") { + if (in_connect_mode) { + std::cout << "Already in connect mode." << std::endl; + continue; + } + in_connect_mode = true; // 进入连接模式 + std::cout << "Enter the gateway IP address: "; + std::cin >> ip; + std::cout << "Enter the gateway port: "; + std::cin >> port; + ConnectToGateway(ip, port); + } else if (command == "exitconnect") { + if (!in_connect_mode) { + std::cout << "Not in connect mode." << std::endl; + continue; + } + in_connect_mode = false; // 退出连接模式 + std::cout << "Exiting connect mode." << std::endl; + } else if (command == "exit") { + exit_flag = true; // 设置退出标志 + std::cout << "Exiting program." << std::endl; + // 关闭所有套接字 + for (auto& sock_pair : sockets) { + shutdown(sock_pair.first, SHUT_RDWR); // 关闭套接字的发送和接收 + close(sock_pair.first); + } + sockets.clear(); + // 等待所有线程结束 + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); + } + } + threads.clear(); + break; // 退出主循环 + } else { + std::cout << "Unknown command" << std::endl; + } + } + + return 0; +} \ No newline at end of file