#include #include #include #include #include #include #include #include #include // 包含TCPClient头文件 #include "IVrTCPClient.h" class TCPClientTest { private: IVrTCPClient* m_pClient; std::atomic m_bRunning; std::atomic m_bConnected; std::string m_sServerIP; int m_nPort; std::atomic m_nRecvCount; std::atomic m_nSendCount; std::atomic m_nTotalRecvBytes; std::thread m_sendThread; std::thread m_statsThread; std::mutex m_consoleMutex; std::chrono::steady_clock::time_point m_startTime; // 测试配置 bool m_bAutoSend; // 是否自动发送测试数据 int m_nSendInterval; // 发送间隔(毫秒) int m_nSendSize; // 每次发送的数据大小(字节) public: /** * @brief 构造函数 * @param serverIP 服务器IP地址 * @param port 服务器端口 * @param autoSend 是否自动发送测试数据 * @param sendInterval 发送间隔(毫秒) * @param sendSize 每次发送的数据大小(字节) */ TCPClientTest(const std::string& serverIP, int port, bool autoSend = false, int sendInterval = 1000, int sendSize = 64) : m_pClient(nullptr), m_bRunning(false), m_bConnected(false), m_sServerIP(serverIP), m_nPort(port), m_nRecvCount(0), m_nSendCount(0), m_nTotalRecvBytes(0), m_bAutoSend(autoSend), m_nSendInterval(sendInterval), m_nSendSize(sendSize) { // 创建TCPClient实例 m_pClient = IVrTCPClient::CreateInstance(); if (!m_pClient) { std::cerr << "❌ Failed to create TCPClient instance" << std::endl; } } /** * @brief 析构函数 */ ~TCPClientTest() { Stop(); // 等待线程结束 if (m_sendThread.joinable()) { m_sendThread.join(); } if (m_statsThread.joinable()) { m_statsThread.join(); } if (m_pClient) { m_pClient->CloseDevice(); IVrTCPClient::DestroyInstance(m_pClient); m_pClient = nullptr; } } /** * @brief 初始化客户端 * @return true表示成功,false表示失败 */ bool Initialize() { if (!m_pClient) { return false; } PrintLog("🔌 Connecting to " + m_sServerIP + ":" + std::to_string(m_nPort)); // 连接设备 int result = m_pClient->LinkDevice(m_sServerIP, m_nPort, true, [this](IVrTCPClient* pClient, bool connected, void* pParam) { this->OnConnectionEvent(pClient, connected, pParam); }, nullptr); if (result != 0) { PrintLog("❌ Failed to connect to server, error code: " + std::to_string(result)); return false; } // 启动工作线程 result = m_pClient->StartWork( [this](IVrTCPClient* pClient, const char* pData, const int nLen, void* pParam) { this->OnDataReceived(pClient, pData, nLen, pParam); }, nullptr); if (result != 0) { PrintLog("❌ Failed to start client work thread, error code: " + std::to_string(result)); return false; } PrintLog("✅ Client initialized successfully"); return true; } /** * @brief 启动客户端 * @return true表示成功,false表示失败 */ bool Start() { m_bRunning = true; m_startTime = std::chrono::steady_clock::now(); // 启动统计线程 m_statsThread = std::thread(&TCPClientTest::StatsLoop, this); // 如果启用自动发送,启动发送线程 if (m_bAutoSend) { m_sendThread = std::thread(&TCPClientTest::SendDataLoop, this); PrintLog("📤 Auto-send enabled: " + std::to_string(m_nSendSize) + " bytes every " + std::to_string(m_nSendInterval) + " ms"); } PrintLog("🚀 Client started, waiting for data..."); return true; } /** * @brief 停止客户端 */ void Stop() { m_bRunning = false; // 等待线程结束 if (m_sendThread.joinable()) { m_sendThread.join(); } if (m_statsThread.joinable()) { m_statsThread.join(); } PrintLog("🛑 Client stopped"); PrintFinalStats(); } /** * @brief 获取接收计数 * @return 接收的消息数量 */ int GetRecvCount() const { return m_nRecvCount.load(); } /** * @brief 获取发送计数 * @return 发送的消息数量 */ int GetSendCount() const { return m_nSendCount.load(); } /** * @brief 获取连接状态 * @return true表示已连接,false表示未连接 */ bool IsConnected() const { return m_bConnected.load(); } /** * @brief 手动发送测试数据 * @param message 要发送的消息 * @return true表示成功,false表示失败 */ bool SendTestData(const std::string& message) { if (!m_pClient || !m_bConnected) { PrintLog("⚠️ Cannot send: not connected"); return false; } bool result = m_pClient->SendData(message.c_str(), static_cast(message.length())); if (result) { m_nSendCount++; PrintLog("📤 Sent: " + message + " (" + std::to_string(message.length()) + " bytes)"); } else { PrintLog("❌ Failed to send data"); } return result; } private: /** * @brief 连接状态回调函数 * @param pClient 客户端指针 * @param connected 是否连接 * @param pParam 参数指针 */ void OnConnectionEvent(IVrTCPClient* pClient, bool connected, void* pParam) { m_bConnected = connected; if (connected) { PrintLog("✅ Connected to server"); } else { PrintLog("❌ Disconnected from server (Auto-reconnect enabled)"); } } /** * @brief 数据接收回调函数 * @param pClient 客户端指针 * @param pData 数据指针 * @param nLen 数据长度 * @param pParam 参数指针 */ void OnDataReceived(IVrTCPClient* pClient, const char* pData, const int nLen, void* pParam) { m_nRecvCount++; m_nTotalRecvBytes += nLen; // 打印接收到的数据(限制长度) std::string data(pData, std::min(nLen, 100)); if (nLen > 100) { data += "..."; } PrintLog("📥 Received #" + std::to_string(m_nRecvCount.load()) + ": [" + std::to_string(nLen) + " bytes] " + data); } /** * @brief 自动发送数据循环 */ void SendDataLoop() { int counter = 0; while (m_bRunning) { if (m_bConnected && m_pClient) { // 构造测试数据 std::string message = "Client-Test-" + std::to_string(++counter); // 填充到指定大小 if (message.length() < static_cast(m_nSendSize)) { message.append(m_nSendSize - message.length(), 'X'); } else if (message.length() > static_cast(m_nSendSize)) { message.resize(m_nSendSize); } bool result = m_pClient->SendData(message.c_str(), static_cast(message.length())); if (result) { m_nSendCount++; } else { PrintLog("❌ Failed to send data"); } } std::this_thread::sleep_for(std::chrono::milliseconds(m_nSendInterval)); } } /** * @brief 统计信息循环打印 */ void StatsLoop() { while (m_bRunning) { std::this_thread::sleep_for(std::chrono::seconds(5)); if (m_bRunning) { PrintStats(); } } } /** * @brief 打印当前统计信息 */ void PrintStats() { auto now = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(now - m_startTime).count(); if (duration == 0) duration = 1; // 避免除零 double recvRate = static_cast(m_nRecvCount.load()) / duration; double sendRate = static_cast(m_nSendCount.load()) / duration; double bandwidth = static_cast(m_nTotalRecvBytes.load()) / duration / 1024.0; // KB/s std::ostringstream oss; oss << "\n📊 Statistics (Running " << duration << "s)" << "\n Connected: " << (m_bConnected ? "Yes" : "No") << "\n Received: " << m_nRecvCount.load() << " msgs (" << std::fixed << std::setprecision(2) << recvRate << " msg/s)" << "\n Sent: " << m_nSendCount.load() << " msgs (" << std::fixed << std::setprecision(2) << sendRate << " msg/s)" << "\n Bandwidth: " << std::fixed << std::setprecision(2) << bandwidth << " KB/s" << "\n Total Recv: " << m_nTotalRecvBytes.load() << " bytes"; PrintLog(oss.str()); } /** * @brief 打印最终统计信息 */ void PrintFinalStats() { auto now = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(now - m_startTime).count(); if (duration == 0) duration = 1; std::ostringstream oss; oss << "\n📈 Final Statistics:" << "\n Total Runtime: " << duration << " seconds" << "\n Total Received: " << m_nRecvCount.load() << " messages" << "\n Total Sent: " << m_nSendCount.load() << " messages" << "\n Total Bytes Received: " << m_nTotalRecvBytes.load() << " bytes" << "\n Average Receive Rate: " << std::fixed << std::setprecision(2) << (static_cast(m_nRecvCount.load()) / duration) << " msg/s" << "\n Average Send Rate: " << std::fixed << std::setprecision(2) << (static_cast(m_nSendCount.load()) / duration) << " msg/s"; PrintLog(oss.str()); } /** * @brief 线程安全的日志打印 * @param message 日志消息 */ void PrintLog(const std::string& message) { std::lock_guard lock(m_consoleMutex); auto now = std::time(nullptr); char timeStr[20]; std::strftime(timeStr, sizeof(timeStr), "%H:%M:%S", std::localtime(&now)); std::cout << "[" << timeStr << "] " << message << std::endl; } }; int main(int argc, char* argv[]) { std::cout << "TCP Client Test Program" << std::endl; std::cout << "=======================" << std::endl; // 默认连接参数 std::string serverIP = "127.0.0.1"; int port = 8080; if (argc > 1) { serverIP = argv[1]; } if (argc > 2) { port = std::stoi(argv[2]); } TCPClientTest clientTest(serverIP, port); // 初始化客户端 if (!clientTest.Initialize()) { std::cerr << "Failed to initialize client" << std::endl; return -1; } // 启动客户端 if (!clientTest.Start()) { std::cerr << "Failed to start client" << std::endl; return -1; } // 运行一段时间或等待用户输入 std::cout << "Client is running. Press Enter to stop..." << std::endl; while(true){ std::cin.get(); std::this_thread::sleep_for(std::chrono::seconds(10)); } // 停止客户端 clientTest.Stop(); std::cout << "TCP Client Test completed!" << std::endl; return 0; }