首先,从 官网下载打包文件。
如果项目是32位+debug+unicode,则hpsocket的lib也要用对应版本。

image.png
头文件

image.png
include头文件
//hpsocket
#include "include/hpsocket/HPTypeDef.h"
#include "include/hpsocket/HPSocket4C-SSL.h"
#ifdef _DEBUG
# pragma comment(lib, "include/hpsocket/lib/HPSocket4C_UD.lib")
#else
# pragma comment(lib, "include/hpsocket/lib/HPSocket4C_U.lib")
#endif
.h
定义变量和回调函数
HP_HttpClientListener m_HttpClientListener;
HP_HttpClient m_HttpClient;
static En_HP_HttpParseResult __stdcall OnHeader(HP_HttpClient pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue);
static En_HP_HttpParseResult __stdcall OnHeadersComplete(HP_HttpClient pSender, CONNID dwConnID);
static En_HP_HttpParseResult __stdcall OnUpgrade(HP_HttpClient pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType);
static En_HP_HttpParseResult __stdcall OnBody(HP_HttpClient pSender, CONNID dwConnID, const BYTE* pData, int iLength);
static En_HP_HttpParseResult __stdcall OnMessageComplete(HP_HttpClient pSender, CONNID dwConnID);
static En_HP_HandleResult __stdcall OnClose(HP_Client pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode);
static En_HP_HandleResult __stdcall OnWSMessageHeader(HP_HttpClient pSender, HP_CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen);
static En_HP_HandleResult __stdcall OnWSMessageBody(HP_HttpClient pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength);
static En_HP_HandleResult __stdcall OnWSMessageComplete(HP_HttpClient pSender, HP_CONNID dwConnID);
.cpp
实现回调函数
//实现回调函数
EnHttpParseResult CFrameWnd::OnHeader(HP_HttpClient pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)
{
printf("HP_Client:OnHeader-> %s: %s\n", lpszName, lpszValue);
//::PostOnHeader(dwConnID, lpszName, lpszValue);
return HPR_OK;
}
EnHttpParseResult CFrameWnd::OnHeadersComplete(HP_HttpClient pSender, CONNID dwConnID)
{
printf("HP_Client:OnHeadersComplete\n");
return HPR_OK;
}
EnHttpParseResult CFrameWnd::OnUpgrade(HP_HttpClient pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType)
{
printf("HP_Client:OnUpgrade\n");
/*
if (enUpgradeType == HUT_WEB_SOCKET)
{
m_spThis->m_bWebSocket = TRUE;
m_spThis->OnCbnSelchangeMethod();
}
*/
return HPR_OK;
}
//pData指向的缓冲区很大,并且是重复利用,不会用\0结尾,需要自己根据长度拷贝过去
EnHttpParseResult CFrameWnd::OnBody(HP_HttpClient pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
printf("HP_Client::OnBody %d bytes\n", iLength);
BYTE* p = new BYTE[iLength + 1];
memset(p, '\0', iLength + 1);
memcpy(p, pData, iLength);
string str = StringParse::UTF8ToGB((char*)p);
printf("p_res:%s\n", str.c_str());
//::PostOnBody(dwConnID, pData, iLength);
return HPR_OK;
}
EnHttpParseResult CFrameWnd::OnMessageComplete(HP_HttpClient pSender, CONNID dwConnID)
{
return HPR_OK;
}
EnHandleResult CFrameWnd::OnClose(HP_Client pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
printf("HP_Client:OnClose\n");
return HR_OK;
}
EnHandleResult CFrameWnd::OnWSMessageHeader(HP_HttpClient pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
{
printf("HP_Client:OnWSMessageHeader\n");
return HR_OK;
}
EnHandleResult CFrameWnd::OnWSMessageBody(HP_HttpClient pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
//::PostOnWSMessageBody(dwConnID, pData, iLength);
printf("HP_Client::OnWSMessageBody %d bytes\n", iLength);
BYTE* p = new BYTE[iLength+1];
memset(p, '\0', iLength+1);
memcpy(p, pData, iLength);
string str = StringParse::UTF8ToGB((char*)p);
printf("str:%s\n", str.c_str());
return HR_OK;
}
EnHandleResult CFrameWnd::OnWSMessageComplete(HP_HttpClient pSender, CONNID dwConnID)
{
printf("HP_Client:OnWSMessageComplete\n");
//::PostOnWSMessageComplete(dwConnID);
BYTE iOperationCode;
ASSERT(::HP_HttpClient_GetWSMessageState(pSender, nullptr, nullptr, &iOperationCode, nullptr, nullptr, nullptr));
if (iOperationCode == 0x8)
return HR_ERROR;
return HR_OK;
}
.cpp中处理逻辑,实现http功能和wss功能
//初始化
void CFrameWnd::InitHp() {
// 加载 Cookie
::HP_HttpCookie_MGR_LoadFromFile(DEFAULT_COOKIE_FILE, FALSE);
// 创建监听器
m_HttpClientListener = ::Create_HP_HttpClientListener();
::HP_Set_FN_HttpClient_OnHeader(m_HttpClientListener, OnHeader);
//这4个是强制必须设置的回调函数
::HP_Set_FN_HttpClient_OnHeadersComplete(m_HttpClientListener, OnHeadersComplete);
::HP_Set_FN_HttpClient_OnBody(m_HttpClientListener, OnBody);
::HP_Set_FN_HttpClient_OnMessageComplete(m_HttpClientListener, OnMessageComplete);
::HP_Set_FN_HttpClient_OnClose(m_HttpClientListener, OnClose);
//::HP_Set_FN_HttpClient_OnPullReceive(m_HttpClientListener, OnPullReceive);
//::HP_Set_FN_HttpClient_OnConnect(m_HttpClientListener, OnConnect);
//::HP_Set_FN_HttpClient_OnRequest(m_HttpClientListener, OnRequest);
//::HP_Set_FN_HttpClient_OnBody(m_HttpClientListener, OnBody);
//ws要用到的回调函数
::HP_Set_FN_HttpClient_OnUpgrade(m_HttpClientListener, OnUpgrade);
::HP_Set_FN_HttpClient_OnWSMessageHeader(m_HttpClientListener, OnWSMessageHeader);
::HP_Set_FN_HttpClient_OnWSMessageBody(m_HttpClientListener, OnWSMessageBody);
//::HP_Set_FN_HttpClient_OnDisconnect(m_HttpClientListener, OnDisconnect);
}
//http实现方式1
void CFrameWnd::httpSync(){
HP_HttpClientListener m_hListener = nullptr;
HP_HttpsSyncClient m_pHttpsClient = nullptr;
std::string syggurl = "https://www.baidu.com/";
m_pHttpsClient = Create_HP_HttpsSyncClient(m_hListener);
HP_HttpSyncClient_SetConnectTimeout(m_pHttpsClient, 30000);
HP_HttpSyncClient_SetRequestTimeout(m_pHttpsClient, 30000);
HP_TcpClient_SetSocketBufferSize(m_pHttpsClient, 4 * 1024 * 1024);
HP_SSLClient_SetupSSLContext(m_pHttpsClient, SSL_SM_CLIENT, NULL, NULL, NULL, NULL);
HP_HttpSyncClient_OpenUrl(m_pHttpsClient, "GET", syggurl.c_str(), nullptr, 0, nullptr, 0, FALSE);
LPCBYTE __resp_body_ptr = nullptr;
int ibytelen = 0;
char* p_Gbk = nullptr;
std::string p_res;
if (!HP_HttpSyncClient_GetResponseBody(m_pHttpsClient, &__resp_body_ptr, &ibytelen)) {
return ;
}
p_res = StringParse::UTF8ToGB((char*)__resp_body_ptr);
std::cout << p_res << std::endl;
}
//http实现方式2
void CFrameWnd::http() {
bool succ = false;
//初始化ssl
bool isHttp = false;
if (isHttp) {
m_HttpClient = ::Create_HP_HttpClient(m_HttpClientListener);
succ = ::HP_Client_Start(m_HttpClient, L"www.taokemiao.com", 80, FALSE);
}
else {
m_HttpClient = ::Create_HP_HttpsClient(m_HttpClientListener);
//succ = HP_SSLClient_SetupSSLContext(m_HttpClient, SSL_VM_NONE, cert_path.c_str(), key_path.c_str(), nullptr, nullptr);
succ = HP_SSLClient_SetupSSLContext(m_HttpClient, SSL_SM_CLIENT, NULL, NULL, NULL, NULL);
printf("HP_SSLClient_SetupSSLContext:%d\n", (int)succ);
succ = ::HP_Client_Start(m_HttpClient, L"www.gmiao.com", 443, FALSE);
printf("HP_Client_Start:%d\n", (int)succ);
Sleep(1000);//ssl连接网站需要时间
}
THeader header[] = { {"Content-Type", "text/html"}/*,{"Host","www.gmiao.com:443"}*/};
int iHeaderCount = sizeof(header) / sizeof(THeader);
//succ = HP_HttpClient_SendRequest(m_HttpClient, "GET", "/", header, iHeaderCount, NULL, 0);
//printf("HP_HttpClient_SendRequest:%d\n", (int)succ);
//发送请求
succ = HP_HttpClient_SendGet(m_HttpClient, "/", header, iHeaderCount);
printf("HP_HttpClient_SendGet:%d\n", (int)succ);
}
//websocket功能实现
void CFrameWnd::wss() {
bool succ = false;
std::string key = "dGhlIHNhbXBsZSBub25jZQ=="; // 生成随机的Sec-WebSocket-Key
m_HttpClient = ::Create_HP_HttpsClient(m_HttpClientListener);
succ = HP_SSLClient_SetupSSLContext(m_HttpClient, SSL_SM_CLIENT, NULL, NULL, NULL, NULL);
printf("HP_SSLClient_SetupSSLContext:%d\n", (int)succ);
succ = ::HP_Client_Start(m_HttpClient, L"echo.websocket.org", 443, FALSE);
printf("HP_Client_Start:%d\n", (int)succ);
Sleep(1000);//ssl连接需要时间
THeader header[] = { {"Upgrade", "websocket"}, {"Connection", "Upgrade"}, {"Sec-WebSocket-Key", key.c_str()}, {"Sec-WebSocket-Version", "13"}};
int iHeaderCount = sizeof(header) / sizeof(THeader);
//发送请求,告诉服务器把【此连接】从http协议升级为wss协议
succ = HP_HttpClient_SendGet(m_HttpClient, "/", header, iHeaderCount);
printf("HP_HttpClient_SendGet:%d\n", (int)succ);
Sleep(3000);//等待服务器返回Upgrade: websocket
//发送ws消息
static const BYTE MASK_KEY[] = { 0x1, 0x2, 0x3, 0x4 };
string data = "hello";
succ = ::HP_HttpClient_SendWSMessage(m_HttpClient, TRUE, 0, 0x1, MASK_KEY, (BYTE*)data.c_str(), data.size(), data.size());
printf("HP_HttpClient_SendWSMessage:%d\n", (int)succ);
}
websocket原理:
1,client_start连接服务器host并返回连接
2,用http get方式通过此返回的连接发送HEADER{ upgrade: websocket, connection: Upgrade,Sec-WebSocket-Key:xxxx},告诉服务器把此连接从http协议升级为websocket协议,
3、服务器会返回upgrade:websocket和sec-websocket-accept的header,如果收到这个表示现在已经升级为websocket连接
4、可以用HP_HttpClient_SendWSMessage给服务器发送websocket消息了

image.png