# proxy_1 **Repository Path**: qq2820/proxy_1 ## Basic Information - **Project Name**: proxy_1 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-09-19 - **Last Updated**: 2025-09-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 分析这个代理服务器代码后,我发现在多个浏览器页面并发访问时会出现卡顿的主要原因和优化方案: ## 主要问题分析 ### 1. 缓冲区大小问题 ```cpp // 当前代码中的问题 char buffer[bufferSize]; // bufferSize可能太小 ``` ### 2. 阻塞I/O导致的性能瓶颈 ```cpp // TunnelData函数中的poll超时设置过长 int32_t ret = poll(fds, 2, 1000); // 1秒超时太长 ``` ### 3. 连接处理效率低 ## 具体优化方案 ### 1. 优化缓冲区大小 ```cpp // 在proxy_server.h中增大缓冲区 static const size_t bufferSize = 65536; // 从默认大小改为64KB // 或者在TunnelData中使用更大的缓冲区 void ProxyServer::TunnelData(int32_t client, int32_t server) { struct pollfd fds[2]; fds[0].fd = client; fds[0].events = POLLIN; fds[1].fd = server; fds[1].events = POLLIN; // 使用更大的缓冲区 char buffer[65536]; // 64KB缓冲区 bool clientClosed = false; bool serverClosed = false; while (!clientClosed && !serverClosed && running_) { // 减少poll超时时间,提高响应性 int32_t ret = poll(fds, 2, 100); // 100ms而不是1000ms if (HandlePollError(ret, errno)) { break; } if (ret == 0) { continue; } if (CheckPollHupOrErr(fds)) { break; } // 优化数据传输逻辑 if (fds[0].revents & POLLIN) { clientClosed = TransferDataOptimized(client, server, buffer, sizeof(buffer), stats_); if (clientClosed) { continue; } } if (fds[1].revents & POLLIN) { serverClosed = TransferDataOptimized(server, client, buffer, sizeof(buffer), stats_); } } } ``` ### 2. 优化数据传输函数 ```cpp // 替换原来的TransferData函数 static bool TransferDataOptimized(int32_t srcFd, int32_t dstFd, char *buffer, size_t bufferSize, std::shared_ptr stats) { // 尝试读取更多数据 int32_t n = recv(srcFd, buffer, bufferSize, MSG_DONTWAIT); if (n <= 0) { if (n == 0) return true; // 连接关闭 if (errno == EAGAIN || errno == EWOULDBLOCK) { return false; // 暂时没有数据,继续 } return true; // 错误,关闭连接 } stats->bytesReceived += n; // 确保完整发送数据 size_t totalSent = 0; while (totalSent < static_cast(n)) { int32_t sent = send(dstFd, buffer + totalSent, n - totalSent, MSG_NOSIGNAL); if (sent <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; // 重试 } return true; // 发送失败 } totalSent += sent; stats->bytesSent += sent; } return false; } ``` ### 3. 优化Socket设置 ```cpp bool ProxyServer::SetSocketTimeout(int32_t socket) { // 设置更短的超时时间 struct timeval timeout; timeout.tv_sec = 10; // 从30秒改为10秒 timeout.tv_usec = 0; if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { return false; } // 添加更多Socket优化选项 int flag = 1; // 禁用Nagle算法,减少延迟 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); // 设置更大的缓冲区 int buffer_size = 65536; setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buffer_size, sizeof(buffer_size)); setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buffer_size, sizeof(buffer_size)); return true; } ``` ### 4. 优化连接建立过程 ```cpp int ProxyServer::ConnectToServer(const std::string &host, int port) { int serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket < 0) { std::cerr << "无法创建socket" << std::endl; return -1; } // 优化超时设置 struct timeval timeout; timeout.tv_sec = 5; // 从10秒改为5秒 timeout.tv_usec = 0; if (setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0 || setsockopt(serverSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) { std::cerr << "设置socket超时选项失败" << std::endl; close(serverSocket); return -1; } // 添加TCP优化选项 int flag = 1; setsockopt(serverSocket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); // 设置更大的缓冲区 int buffer_size = 65536; setsockopt(serverSocket, SOL_SOCKET, SO_RCVBUF, &buffer_size, sizeof(buffer_size)); setsockopt(serverSocket, SOL_SOCKET, SO_SNDBUF, &buffer_size, sizeof(buffer_size)); struct hostent *server = gethostbyname(host.c_str()); if (server == nullptr) { std::cerr << "无法解析主机: " << host << std::endl; close(serverSocket); return -1; } struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); memcpy_s(&serverAddr.sin_addr.s_addr, sizeof(serverAddr.sin_addr.s_addr), server->h_addr, server->h_length); if (connect(serverSocket, reinterpret_cast(&serverAddr), sizeof(serverAddr)) < 0) { std::cerr << "无法连接到目标服务器 " << host << ":" << port << std::endl; close(serverSocket); return -1; } return serverSocket; } ``` ### 5. 优化请求头读取 ```cpp bool ProxyServer::ReadRequestHeader(int32_t clientSocket, std::string &requestHeader) { char buffer[8192]; // 增大缓冲区 int bytesReceived = 0; // 设置非阻塞模式进行初始读取 int flags = fcntl(clientSocket, F_GETFL, 0); fcntl(clientSocket, F_SETFL, flags | O_NONBLOCK); while ((bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0)) > 0) { buffer[bytesReceived] = '\0'; requestHeader += buffer; stats_->bytesReceived += bytesReceived; if (requestHeader.find("\r\n\r\n") != std::string::npos) { break; } if (requestHeader.size() > maxHeaderSize) { fcntl(clientSocket, F_SETFL, flags); // 恢复原来的标志 return false; } } // 恢复阻塞模式 fcntl(clientSocket, F_SETFL, flags); return bytesReceived > 0 || requestHeader.find("\r\n\r\n") != std::string::npos; } ``` ### 6. 优化线程池大小 ```cpp ProxyServer::ProxyServer(int32_t port, int32_t numThreads) : port_(port), serverSocket_(-1), numThreads_(numThreads), running_(false) { if (numThreads_ <= 0) { // 增加线程数量以处理更多并发连接 numThreads_ = std::thread::hardware_concurrency() * 2; // 改为CPU核心数的2倍 if (numThreads_ <= 0) { numThreads_ = 8; // 从4改为8 } } // ... 其余代码保持不变 } ``` ### 7. 添加连接复用优化 ```cpp // 在HandleClient函数开始时添加 void ProxyServer::HandleClient(int32_t clientSocket) { stats_->activeConnections++; // 优化Socket设置 int flag = 1; setsockopt(clientSocket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); // 设置更大的缓冲区 int buffer_size = 65536; setsockopt(clientSocket, SOL_SOCKET, SO_RCVBUF, &buffer_size, sizeof(buffer_size)); setsockopt(clientSocket, SOL_SOCKET, SO_SNDBUF, &buffer_size, sizeof(buffer_size)); // 设置超时 if (!SetSocketTimeout(clientSocket)) { CleanupConnection(clientSocket); return; } // ... 其余代码保持不变 } ``` ## 主要优化点总结: 1. **增大缓冲区**:从小缓冲区改为64KB,减少系统调用次数 2. **减少poll超时**:从1000ms改为100ms,提高响应性 3. **优化Socket选项**:启用TCP_NODELAY,增大缓冲区 4. **缩短连接超时**:减少等待时间 5. **增加线程数**:提高并发处理能力 6. **优化数据传输**:确保完整传输,处理EAGAIN情况 这些优化可以显著提升代理服务器在多浏览器页面并发访问时的性能表现。