|
|
@ -1,288 +0,0 @@
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include <thread>
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
#include <mutex>
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BUFFER_SIZE 1024
|
|
|
|
|
|
|
|
#define HTTP_SERVER_PORT 8080
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::thread> threads; // 存储所有连接线程
|
|
|
|
|
|
|
|
std::map<int, int> sockets; // 存储套接字
|
|
|
|
|
|
|
|
std::mutex sockets_mutex; // 用于同步访问 sockets
|
|
|
|
|
|
|
|
std::atomic<bool> 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<std::mutex> 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<std::mutex> 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"<<std::endl;
|
|
|
|
|
|
|
|
// return 0;
|
|
|
|
|
|
|
|
std::thread http_server_thread(StartHttpServer);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string command, ip;
|
|
|
|
|
|
|
|
int port;
|
|
|
|
|
|
|
|
bool in_connect_mode = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
|
|
|
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") {
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|