283 lines
10 KiB
C++
283 lines
10 KiB
C++
// 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;
|
||
}
|