// TestEcho-SSL-Console Client // 基于HP-Socket的SSL客户端控制台程序 #include "pch.h" // SSL证书配置(来自helper.cpp) static const char* g_c_lpszPemCert = R"(-----BEGIN CERTIFICATE----- MIIDszCCApugAwIBAgIBATANBgkqhkiG9w0BAQsFADB7MQswCQYDVQQGEwJDTjEL MAkGA1UECAwCR0QxCzAJBgNVBAcMAkdaMQwwCgYDVQQKDANTU1QxDzANBgNVBAsM Bkplc3NtYTETMBEGA1UEAwwKamVzc21hLm9yZzEeMBwGCSqGSIb3DQEJARYPbGRj c2FhQDIxY24uY29tMCAXDTI0MDYyNjA1MjUwOFoYDzIyNDMwNzA5MDUyNTA4WjBu MQswCQYDVQQGEwJDTjELMAkGA1UECAwCR0QxDDAKBgNVBAoMA1NTVDEPMA0GA1UE CwwGSmVzc21hMRMwEQYDVQQDDApqZXNzbWEub3JnMR4wHAYJKoZIhvcNAQkBFg9s ZGNzYWFAMjFjbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCD +MyrJEKCheRoOpMRjR78S8hr9W7XN0/EZWyVKwXRT7EE0aGiQdH/W2a+qpWRMa6E Qi47zdBnt0P8ZoFiItQhuhwUJ064afpVoaHHX25UdbF8r+sRTofadughETBBj2Cf qh0ia6EOB0QvpJpywWmGZPoMtypjbUiTb/YGOJh2qsVr67MN/E48vt7qt0VxF9SE pucvqhraTBljWCeRVCae2c0yBSpq/n+7NhamK7+g3xxCKWRz4pN3wrIoEsXTboTh z940caDgthCc23VJ080DN44jZg6c87huKIuxbebJqw2HCM4DwrW+OSzTLszpFAXZ yarllOzWnBut20zmYnl1AgMBAAGjTTBLMAkGA1UdEwQCMAAwHQYDVR0OBBYEFJ5E RJmJ4pUzEbcU9Yge6nr0oi51MB8GA1UdIwQYMBaAFN49z48DywmoD4cNTQgC6nn2 QJoUMA0GCSqGSIb3DQEBCwUAA4IBAQBpoSFfDDDKMAy95tSROpYu5WSWQXe6B7kl PGJAF6mWe/4b7jHQqDUVkEmFmbMWUAtpTC3P01TrV77dhIosAnC/B76fb7Pto8W4 cjGpWAT0sSegZuhnLtguTGlnR0vVSh/yRRDEtjN8loWpu3BLWVHYOKnn62QGfY0B sRGrfZsKvwB+1w+HOvGopnWv6UYwrzEKthjPMR65rOsoManOv24ua8baJmq0gqF9 752kD8n703uWUBx79/QlNIPMZC1iUIi1mEjyrTgSag6+3sWAIKihaoF/Nf9d01nw iL16EIT5dJ0QJWDCeIxhuTZckw+gL1pBeQU7pqzKHPnvo+8GBnTG -----END CERTIFICATE----- )"; static const char* g_c_lpszPemKey = R"(-----BEGIN ENCRYPTED PRIVATE KEY----- MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIK2UJW9QXIj4CAggA MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCDDZQLhAdT91jd6v/5H0+GBIIE 0PH6tKl+nPi8sU0ryjxDIrHwrT/ZFah+3TAHGE/YFAOZnzRyCFHQTvUZX4p8eSmw WOpt5NBUPJ3mT0Ctt7lGBRy4AXSyBrFSamlTruM3P1e3ijluYjMbweZFfCWPq8c/ jPjbcUkXe6mD96aPSTt/jIunexS8AKovu8c/bFLyTLDk38lATc+GnXQQJ0KiXCRu vpjVSKcv2Br6cWqaNTZ71FvH1RmSD6K6givc0w65pKruHYTMApIRR8YC5Y0vx0gD 6nS12LV/EJEtxTfZFlrzZTRWZISPIzYGuTfS+3bPePlxpbwzhN6vmvgjKhdk+3lN 3W3ZfqODNhoOKG+mG5Fdj7vR2PU1UND6UUd3+FrzWkXikmalAAwKzRLnyTR1T2rl RhM0Qe/HZianeEQTHpCw27gOz1OMw2EKfIEHM6W2BKGOTY5ls5dqgMfP1ZoQUrOr 59tJo4GpWYFGCuHhTEa5OS/gsgnzymGrkuEwPsdSQaBdzV7lFGTv2/ryKX+vNm9V CmKw0nHzOVP19+WL4vPDtbRnLUk8KV9Mg7PdSbGbNcMmTEBk8ju8OvjIUIWZbRTa n5C6fhD1DYZcczmlCILYgXyJISu7EDf3z9cKRAf5VbRAedDMB/xHWmrmlxUJ37Kt tVgaCD0U6Q3q+3y6OOwugc8UbSo4yA/DbLlG0/U7afwQaNxTLa4HGBQljpoNStIt Vgfy2olqHXaf2doSQtsYEl9MHa6neuGfZQMtonDkejnx4KKU+cMhe+KijEUwieYx 7aoPB71b82XODquDPAL5zOegj0eYgKn5iXyOx5W44S34zfclxtxxgfsDJ3qJ9qoL sSenrQ3xAYHJSZRcqEgO31XhoEnkyt1V7G0Bk4/GUMD6uQudr3nsw/ulJpAlNK15 ZxTSKWrtwOWdwcTj6B14K6wcqMFVNF1Ydbv/qp0b5q5S/orYHzRIPcFmdOAIsjyO 6na7+D31BH/4pf+TASBNqRNRw5CBqNcGcfiXk11AywxUnmD5ZvC/C0pTpTD/9qC4 LucWJ0sNAtPq8suFjKqQ+wMvq3rUh050NRm2cm2nUJLxafTnr0v3+kKYbVW8pSWB NMelZMVGF1MDYBujg8Mw/xuMhPeLozCZeKmo7eu7aDMXzQMZLfAEJAzU9Du8H4nq GgQVUgEkS5rdbjZGkHP0FuM8m8lueKEPDYwHCJv9Be5Z/uxp9OO/Lmdlha0J7gJu pihNkAYVxRst96b5okXKooYi/TZxAdThoPYH28VwinGR1I3/8I3M5DbUPIgHhDeB ga3u7jt7ZNDUgavukUD0S7WioRb5ooXrXGZ1xmzKLCmMdCDC5S32fQS0wRGfVoMl hWbaT+0uak+fOpqVRxSNyE3Ek788ua5iPHaTSXJSoe5lv7OQKDSZ/+wFeLmDPf4M BHL2gBLD6RNkz5cWgy14sQcJKNAnyptU4EGPyURZcB8APtB/ITAS2Az/JSxvSBgq g/L1FujnP2QEpWpVKkTNxsF867bUPN34KrlPKYjNqcKA2pD4fkFoKSeeNtOEWa++ d6q9y+mDD97SnIFAAhDFlukzXtyl4MU6uiqRldFiuEt3KzvV19n8M+NyyYIFhfdg 6TkYEbMJPQ/Y3EGNmyMqbFdJzrdl/B8pr7JQnikTfUZZ -----END ENCRYPTED PRIVATE KEY----- )"; static const char* g_c_lpszCAPemCert = R"(-----BEGIN CERTIFICATE----- MIID2TCCAsGgAwIBAgIUM8TTtPU+ejzffYXCcs/zZsU7OuIwDQYJKoZIhvcNAQEL BQAwezELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJHWjEMMAoG A1UECgwDU1NUMQ8wDQYDVQQLDAZKZXNzbWExEzARBgNVBAMMCmplc3NtYS5vcmcx HjAcBgkqhkiG9w0BCQEWD2xkY3NhYUAyMWNuLmNvbTAgFw0yNDA2MjYwNTA0NDNa GA8yMjcwMTEyNDA1MDQ0M1owezELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQsw CQYDVQQHDAJHWjEMMAoGA1UECgwDU1NUMQ8wDQYDVQQLDAZKZXNzbWExEzARBgNV BAMMCmplc3NtYS5vcmcxHjAcBgkqhkiG9w0BCQEWD2xkY3NhYUAyMWNuLmNvbTCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAML+v79+aLQt0Za0dTIZHI5B NDs0g5G8bhdOTlW/kNWflaziZ3GY6d6nJSkQ5e29kyFKxlOD6Gls6bOJ86U71u4R bCmoFvRTDH4q2cJ/+PbiioLpNveDG6lnRCs9JNRQoJrkpRo6urnVnAdsIf6UFjLI dlByNMPGYJ0V8/oKJG5Vu5gcbZV0jVA5+tswkH/zquexEXoKvp18mcwl+pNc/LwW 0WnGj0uoJjxHg4GsS78PASjhxMR/2d/1OpgPauldFaNHjVPtaLqJnuejwA6M6Sz8 iFPybAQAMpHL9W8kf08jtbnFvnm4ibUkQL5h+OJoIEQa9AVZOSoFG2/g5Zcn8X8C AwEAAaNTMFEwHQYDVR0OBBYEFN49z48DywmoD4cNTQgC6nn2QJoUMB8GA1UdIwQY MBaAFN49z48DywmoD4cNTQgC6nn2QJoUMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI hvcNAQELBQADggEBALJnYrYBSZLyYX14FQ04zxG3AX0CtQzNOOa7LDrr+H8Ly+nK qS87gg2njMVZH1zM2demtMwydR/F2Ui8ggaduMvc9h5YgQKEwYl8KarJEY03oZoe zbQGBxCXpDOtMs1vujzcl/iZbSzwEDF3g4la5U8q4MlmfGFKz9CJbvoxecqYA206 nNbW2XZsW/xMiQv6iAw5iP/LOR9HAyxcvXIsL790nfcgnTYLmyP254Dj4outc6R+ PA+f/c1FvkbUBTR5vJt2tsvHcNU218rY2hyOIhDmZeUWprqBO19sUk3scLbVPr3+ WEWEl2XaCekKuPtAnMgVQuFsocXGyiuIhkOe5Z4= -----END CERTIFICATE----- )"; static const int g_c_iVerifyMode = SSL_VM_PEER; static const char* g_c_lpszKeyPassword = "123456"; static const LPCTSTR DEFAULT_ADDRESS = _T("127.0.0.1"); static const USHORT DEFAULT_PORT = 5555; inline static bool writeFile(const std::string& path, const std::vector& data) { std::ofstream f(path, std::ios::binary); if (!f) return false; // 写入数据 f.write(reinterpret_cast(data.data()), data.size()); // 检查是否全部写入成功 if (!f) return false; return true; } // 客户端监听器类 class CClientListener : public CTcpClientListener { private: bool m_bConnected; public: CClientListener() : m_bConnected(false) {} bool IsConnected() const { return m_bConnected; } virtual EnHandleResult OnConnect(ITcpClient* pSender, CONNID dwConnID) override { TCHAR szAddress[100]; int iAddressLen = sizeof(szAddress) / sizeof(TCHAR); USHORT usPort; pSender->GetLocalAddress(szAddress, iAddressLen, usPort); std::wcout << L"[客户端] 连接成功: 本地地址=" << szAddress << L":" << usPort << std::endl; m_bConnected = true; return HR_OK; } virtual EnHandleResult OnHandShake(ITcpClient* pSender, CONNID dwConnID) override { std::wcout << L"[客户端] SSL握手完成" << std::endl; return HR_OK; } virtual EnHandleResult OnReceive(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength) override { std::string strData((char*)pData, iLength); std::cout << "[客户端] 收到服务器数据,长度为:" << iLength << std::endl; return HR_OK; } virtual EnHandleResult OnSend(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength) override { return HR_OK; } virtual EnHandleResult OnClose(ITcpClient* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode) override { if (iErrorCode == SE_OK) { std::wcout << L"[客户端] 连接已关闭" << std::endl; } else { std::wcout << L"[客户端] 连接错误: 错误码=" << iErrorCode << std::endl; } m_bConnected = false; return HR_OK; } }; void PrintMenu() { std::wcout << L"\n----------------------------------------" << std::endl; std::wcout << L"命令菜单:" << std::endl; std::wcout << L" 1 - 发送 'hello' 到服务器" << std::endl; std::wcout << L" Q - 断开连接并退出" << std::endl; std::wcout << L"----------------------------------------" << std::endl; std::wcout << L"请输入命令: "; } int main() { // 设置控制台UTF-8编码和locale SetConsoleOutputCP(CP_UTF8); std::locale::global(std::locale("")); std::wcout.imbue(std::locale("")); std::wcout << L"========================================" << std::endl; std::wcout << L" HP-Socket SSL Client 控制台演示程序" << std::endl; std::wcout << L"========================================" << std::endl; std::wcout << std::endl; // 创建监听器和客户端 CClientListener listener; CSSLClientPtr client(&listener); // 初始化SSL上下文 std::wcout << L"[客户端] 正在初始化SSL环境..." << std::endl; if (!client->SetupSSLContextByMemory(g_c_iVerifyMode, g_c_lpszPemCert, g_c_lpszPemKey, g_c_lpszKeyPassword, g_c_lpszCAPemCert)) { std::wcout << L"[客户端] SSL初始化失败!错误码: " << client->GetLastError() << std::endl; std::wcout << L"按任意键退出..." << std::endl; _getch(); return 1; } std::wcout << L"[客户端] SSL环境初始化成功" << std::endl; // 连接服务器 std::wcout << L"[客户端] 正在连接服务器 " << DEFAULT_ADDRESS << L":" << DEFAULT_PORT << L" ..." << std::endl; if (!client->Start(DEFAULT_ADDRESS, DEFAULT_PORT, FALSE)) { std::wcout << L"[客户端] 连接失败!错误码: " << client->GetLastError() << std::endl; std::wcout << L"按任意键退出..." << std::endl; _getch(); return 1; } // 等待连接完成 int waitCount = 0; while (!listener.IsConnected() && waitCount < 50) { Sleep(100); waitCount++; } if (!listener.IsConnected()) { std::wcout << L"[客户端] 连接超时!" << std::endl; client->Stop(); client->CleanupSSLContext(); std::wcout << L"按任意键退出..." << std::endl; _getch(); return 1; } std::wcout << L"[客户端] 已连接到服务器,可以开始发送消息" << std::endl; // 主循环 - 等待用户输入命令 PrintMenu(); bool bRunning = true; while (bRunning) { if (_kbhit()) { char ch = _getch(); std::cout << ch << std::endl; if (ch == '1') { // 发送 "hello" 到服务器 std::string message = "hello"; if (client->Send((const BYTE*)message.c_str(), (int)message.length())) { std::cout << "[客户端] 发送消息: \"" << message << "\"" << std::endl; } else { std::wcout << L"[客户端] 发送失败!错误码: " << client->GetLastError() << std::endl; } PrintMenu(); } else if (ch == 'q' || ch == 'Q') { bRunning = false; } else { std::wcout << L"无效命令,请重新输入。" << std::endl; PrintMenu(); } } Sleep(100); } // 断开连接 std::wcout << L"[客户端] 正在断开连接..." << std::endl; if (client->Stop()) { std::wcout << L"[客户端] 已断开连接" << std::endl; } // 清理SSL上下文 client->CleanupSSLContext(); std::wcout << L"按任意键退出..." << std::endl; _getch(); return 0; }