Files
--hp-socket-TCP--ssl--/Client/main.cpp
2026-01-23 08:39:07 +08:00

283 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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<unsigned char>& data) {
std::ofstream f(path, std::ios::binary);
if (!f) return false;
// 写入数据
f.write(reinterpret_cast<const char*>(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;
}