Files
--hp-socket-TCP--ssl--/Client/main.cpp

283 lines
10 KiB
C++
Raw Normal View History

2026-01-23 08:39:07 +08:00
// 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;
}