首先,HPSocket是一个很好的开源网络项目,支持跨平台,Windows,Linux,Android,MacOS等等。但是就Windows平台而言,它的开发环境是VisualStudio。由于c++编译器的差异,Mingw和Mingw64是无法调用HPSocket的c++动态链接库的,因此我们只能使用HPSocket的c语言动态库。但是对于习惯使用c++的人来说,使用c语言是一件感觉很不好的事,就像现代人,突然回到了原始社会一样,在c语言中,没有c++的各种武器,并且函数、变量分散,阅读代码困难。因此自己抛砖引玉,对HPSocket做了下简单的包装,代码如下。
//
// Created by Yoo on 2020/5/26.
//
#ifndef HP_WRAPPER_HPP
#define HP_WRAPPER_HPP
#include
#include
#include
#include
#include
#include
#if !defined(MAX)
#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
#endif
#if !defined(MIN)
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
#endif
template
class CBufferPtrT {
public:
explicit CBufferPtrT(size_t size = 0, bool zero = false) {
Reset();
Malloc(size, zero);
}
explicit CBufferPtrT(const T *pch, size_t size) {
Reset();
Copy(pch, size);
}
CBufferPtrT(const CBufferPtrT &other) {
Reset();
Copy(other);
}
template
CBufferPtrT(const CBufferPtrT &other) {
Reset();
Copy(other);
}
~CBufferPtrT() { Free(); }
T *Malloc(size_t size = 1, bool zero = false) {
Free();
return Alloc(size, zero, false);
}
T *Realloc(size_t size, bool zero = false) {
return Alloc(size, zero, true);
}
void Free() {
if (m_pch) {
free(m_pch);
Reset();
}
}
template
CBufferPtrT &Copy(const CBufferPtrT &other) {
if ((void *) &other != (void *) this)
Copy(other.Ptr(), other.Size());
return *this;
}
CBufferPtrT &Copy(const T *pch, size_t size) {
Malloc(size);
if (m_pch)
memcpy(m_pch, pch, size * sizeof(T));
return *this;
}
template
CBufferPtrT &Cat(const CBufferPtrT &other) {
if ((void *) &other != (void *) this)
Cat(other.Ptr(), other.Size());
return *this;
}
CBufferPtrT &Cat(const T *pch, size_t size = 1) {
size_t pre_size = m_size;
Realloc(m_size + size);
if (m_pch)
memcpy(m_pch + pre_size, pch, size * sizeof(T));
return *this;
}
template
bool Equal(const CBufferPtrT &other) const {
if ((void *) &other == (void *) this)
return true;
else if (m_size != other.Size())
return false;
else if (m_size == 0)
return true;
else
return (memcmp(m_pch, other.Ptr(), m_size * sizeof(T)) == 0);
}
bool Equal(T *pch) const {
if (m_pch == pch)
return true;
else if (!m_pch || !pch)
return false;
else
return (memcmp(m_pch, pch, m_size * sizeof(T)) == 0);
}
T *Ptr() { return m_pch; }
const T *Ptr() const { return m_pch; }
T &Get(int i) { return *(m_pch + i); }
const T &Get(int i) const { return *(m_pch + i); }
size_t Size() const { return m_size; }
bool IsValid() const { return m_pch != 0; }
operator T *() { return Ptr(); }
operator const T *() const { return Ptr(); }
T &operator[](int i) { return Get(i); }
const T &operator[](int i) const { return Get(i); }
bool operator==(T *pv) const { return Equal(pv); }
template
bool operator==(const CBufferPtrT &other) { return Equal(other); }
CBufferPtrT &operator=(const CBufferPtrT &other) { return Copy(other); }
template
CBufferPtrT &operator=(const CBufferPtrT &other) { return Copy(other); }
private:
void Reset() {
m_pch = 0;
m_size = 0;
m_capacity = 0;
}
size_t GetAllocSize(size_t size) { return MAX(size, MIN(size * 2, m_size + MAX_CACHE_SIZE)); }
T *Alloc(size_t size, bool zero = false, bool is_realloc = false) {
if (size >= 0 && size != m_size) {
size_t rsize = GetAllocSize(size);
if (size > m_capacity || rsize < m_size) {
m_pch = is_realloc ?
(T *) realloc(m_pch, rsize * sizeof(T)) :
(T *) malloc(rsize * sizeof(T));
if (m_pch || rsize == 0) {
m_size = size;
m_capacity = rsize;
} else
Reset();
} else
m_size = size;
}
if (zero && m_pch)
memset(m_pch, 0, m_size * sizeof(T));
return m_pch;
}
private:
T *m_pch;
size_t m_size;
size_t m_capacity;
};
typedef CBufferPtrT CCharBufferPtr;
typedef CBufferPtrT CByteBufferPtr;
typedef CByteBufferPtr CBufferPtr;
/**
* 服务端基础类
* @tparam SERVER
* @tparam T
* @tparam PORT
*/
template
class serverBase {
public:
explicit serverBase(SERVER *pServer) : m_pServer(pServer) {
}
serverBase() = delete;
BOOL SetPkgInfo(HP_Server pSender, HP_CONNID dwConnID) {
return HP_Server_SetConnectionExtra(pSender, dwConnID, new T);
}
T *FindPkgInfo(HP_Server pSender, HP_CONNID dwConnID) {
PVOID pInfo = nullptr;
HP_Server_GetConnectionExtra(pSender, dwConnID, &pInfo);
return reinterpret_cast(pInfo);
}
void RemovePkgInfo(HP_Server pSender, HP_CONNID dwConnID) {
T *pInfo = FindPkgInfo(pSender, dwConnID);
assert(pInfo != nullptr);
delete pInfo;
}
BOOL start() {
return HP_Server_Start(*m_pServer, "0.0.0.0", PORT);
}
BOOL stop() {
return HP_Server_Stop(*m_pServer);
}
BOOL sendPack(HP_CONNID dwConnID, const BYTE *pBuffer, int iLength) {
return HP_Server_Send(*m_pServer, dwConnID, pBuffer, iLength);
}
BOOL sendPacks(HP_CONNID dwConnID, const WSABUF pBuffers[], int iCount) {
return HP_Server_SendPackets(*m_pServer, dwConnID, pBuffers, iCount);
}
private:
SERVER *m_pServer;
};
/**
* 客户端基础类
* @tparam CLIENT
* @tparam T
* @tparam IP_0
* @tparam IP_1
* @tparam IP_2
* @tparam IP_3
* @tparam PORT
*/
template
class clientBase {
public:
explicit clientBase(CLIENT *pClient) : m_pClient(pClient) {
sprintf(m_IP, "%d.%d.%d.%d", IP_0, IP_1, IP_2, IP_3);
}
clientBase() = delete;
void SetPkgInfo(HP_Client pSender) {
HP_Client_SetExtra(pSender, new T);
}
T *FindPkgInfo(HP_Client pSender) {
PVOID pInfo = HP_Client_GetExtra(pSender);
return reinterpret_cast(pInfo);
}
void RemovePkgInfo(HP_Client pSender) {
T *pInfo = FindPkgInfo(pSender);
assert(pInfo != nullptr);
delete pInfo;
}
BOOL start() {
return HP_Client_Start(*m_pClient, m_IP, PORT, TRUE);
}
BOOL stop() {
return HP_Client_Stop(*m_pClient);
}
BOOL sendPack(const BYTE *pBuffer, int iLength) {
return HP_Client_Send(*m_pClient, pBuffer, iLength);
}
BOOL sendPacks(const WSABUF pBuffers[], int iCount) {
return HP_Client_SendPackets(*m_pClient, pBuffers, iCount);
}
private:
CLIENT *m_pClient;
char m_IP[16] = {0};
};
/**
* pull类型服务端监听器
*/
class pullServerListener {
public:
virtual En_HP_HandleResult onPrepareListen(HP_Server pSender, SOCKET soListen) = 0;
virtual En_HP_HandleResult onAccept(HP_Server pSender, HP_CONNID dwConnID, SOCKET soClient) = 0;
virtual En_HP_HandleResult onSend(HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) = 0;
virtual En_HP_HandleResult onReceive(HP_Server pSender, HP_CONNID dwConnID, int iLength) = 0;
virtual En_HP_HandleResult
onClose(HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) = 0;
virtual En_HP_HandleResult onShutdown(HP_Server pSender) = 0;
};
/**
* pull类型客户端监听器
*/
class pullClientListener {
public:
virtual En_HP_HandleResult onConnect(HP_Client pSender, HP_CONNID dwConnID) = 0;
virtual En_HP_HandleResult onSend(HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) = 0;
virtual En_HP_HandleResult onReceive(HP_Client pSender, HP_CONNID dwConnID, int iLength) = 0;
virtual En_HP_HandleResult
onClose(HP_Client pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) = 0;
};
/**
* pack类型服务端监听器
*/
class packServerListener {
public:
virtual En_HP_HandleResult onPrepareListen(HP_Server pSender, SOCKET soListen) = 0;
virtual En_HP_HandleResult onAccept(HP_Server pSender, HP_CONNID dwConnID, SOCKET soClient) = 0;
virtual En_HP_HandleResult onSend(HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) = 0;
virtual En_HP_HandleResult onReceive(HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) = 0;
virtual En_HP_HandleResult
onClose(HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) = 0;
virtual En_HP_HandleResult onShutdown(HP_Server pSender) = 0;
};
/**
* pack类型客户端监听器
*/
class packClientListener {
public:
virtual En_HP_HandleResult onConnect(HP_Client pSender, HP_CONNID dwConnID) = 0;
virtual En_HP_HandleResult onSend(HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) = 0;
virtual En_HP_HandleResult onReceive(HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) = 0;
virtual En_HP_HandleResult
onClose(HP_Client pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) = 0;
};
/**
* pull类型服务端基础类
* @tparam T
* @tparam PORT
*/
template
class pullServer : public serverBase, public pullServerListener {
public:
pullServer() : serverBase(&m_pServer) {
pThis = this;
m_pListener = Create_HP_TcpPullServerListener();
m_pServer = Create_HP_TcpPullServer(m_pListener);
HP_Set_FN_Server_OnPrepareListen(m_pListener, OnPrepareListen);
HP_Set_FN_Server_OnAccept(m_pListener, OnAccept);
HP_Set_FN_Server_OnSend(m_pListener, OnSend);
HP_Set_FN_Server_OnPullReceive(m_pListener, OnReceive);
HP_Set_FN_Server_OnClose(m_pListener, OnClose);
HP_Set_FN_Server_OnShutdown(m_pListener, OnShutdown);
}
~pullServer() {
Destroy_HP_TcpPullServerListener(m_pListener);
Destroy_HP_TcpPullServer(m_pServer);
}
private:
static En_HP_HandleResult __HP_CALL OnPrepareListen(HP_Server pSender, SOCKET soListen) {
return pThis->onPrepareListen(pSender, soListen);
}
static En_HP_HandleResult __HP_CALL OnAccept(HP_Server pSender, HP_CONNID dwConnID, SOCKET soClient) {
return pThis->onAccept(pSender, dwConnID, soClient);
}
static En_HP_HandleResult __HP_CALL OnSend(HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) {
return pThis->onSend(pSender, dwConnID, pData, iLength);
}
static En_HP_HandleResult __HP_CALL OnReceive(HP_Server pSender, HP_CONNID dwConnID, int iLength) {
return pThis->onReceive(pSender, dwConnID, iLength);
}
static En_HP_HandleResult __HP_CALL
OnClose(HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) {
return pThis->onClose(pSender, dwConnID, enOperation, iErrorCode);
}
static En_HP_HandleResult __HP_CALL OnShutdown(HP_Server pSender) {
return pThis->onShutdown(pSender);
}
private:
static pullServer *pThis;
HP_TcpPullServer m_pServer;
HP_TcpPullServerListener m_pListener;
};
template
pullServer *pullServer::pThis = nullptr;
/**
* pull类型客户端基础类
* @tparam T
* @tparam IP_0
* @tparam IP_1
* @tparam IP_2
* @tparam IP_3
* @tparam PORT
*/
template
class pullClient : public clientBase, public pullClientListener {
public:
using __super = clientBase;
explicit pullClient() : __super(&m_pClient) {
pThis = this;
m_pListener = Create_HP_TcpPullClientListener();
m_pClient = Create_HP_TcpPullClient(m_pListener);
HP_Set_FN_Client_OnConnect(m_pListener, OnConnect);
HP_Set_FN_Client_OnSend(m_pListener, OnSend);
HP_Set_FN_Client_OnPullReceive(m_pListener, OnReceive);
HP_Set_FN_Client_OnClose(m_pListener, OnClose);
}
virtual ~pullClient() {
Destroy_HP_TcpPullClientListener(m_pListener);
Destroy_HP_TcpPullClient(m_pClient);
}
private:
static En_HP_HandleResult __HP_CALL OnConnect(HP_Client pSender, HP_CONNID dwConnID) {
return pThis->onConnect(pSender, dwConnID);
}
static En_HP_HandleResult __HP_CALL OnSend(HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) {
return pThis->onSend(pSender, dwConnID, pData, iLength);
}
static En_HP_HandleResult __HP_CALL OnReceive(HP_Client pSender, HP_CONNID dwConnID, int iLength) {
return pThis->onReceive(pSender, dwConnID, iLength);
}
static En_HP_HandleResult __HP_CALL
OnClose(HP_Client pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) {
return pThis->onClose(pSender, dwConnID, enOperation, iErrorCode);
}
protected:
static pullClient *pThis;
HP_TcpPullClient m_pClient;
HP_TcpPullClientListener m_pListener;
};
template
pullClient *pullClient::pThis = nullptr;
/**
* pack类型服务端基础类
* @tparam T
* @tparam PORT
* @tparam MAX_PACKSIZE
* @tparam PACKHEADER_FLAG
*/
template
class packServer : public serverBase, public packServerListener {
public:
packServer() : serverBase(&m_pServer) {
pThis = this;
m_pListener = Create_HP_TcpPackServerListener();
m_pServer = Create_HP_TcpPackServer(m_pListener);
HP_Set_FN_Server_OnPrepareListen(m_pListener, OnPrepareListen);
HP_Set_FN_Server_OnAccept(m_pListener, OnAccept);
HP_Set_FN_Server_OnSend(m_pListener, OnSend);
HP_Set_FN_Server_OnReceive(m_pListener, OnReceive);
HP_Set_FN_Server_OnClose(m_pListener, OnClose);
HP_Set_FN_Server_OnShutdown(m_pListener, OnShutdown);
HP_TcpPackServer_SetMaxPackSize(m_pServer, MAX_PACKSIZE);
HP_TcpPackServer_SetPackHeaderFlag(m_pServer, PACKHEADER_FLAG);
}
~packServer() {
Destroy_HP_TcpPackServerListener(m_pListener);
Destroy_HP_TcpPackServer(m_pServer);
}
private:
static En_HP_HandleResult __HP_CALL OnPrepareListen(HP_Server pSender, SOCKET soListen) {
return pThis->onPrepareListen(pSender, soListen);
}
static En_HP_HandleResult __HP_CALL OnAccept(HP_Server pSender, HP_CONNID dwConnID, SOCKET soClient) {
return pThis->onAccept(pSender, dwConnID, soClient);
}
static En_HP_HandleResult __HP_CALL OnSend(HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) {
return pThis->onSend(pSender, dwConnID, pData, iLength);
}
static En_HP_HandleResult __HP_CALL
OnReceive(HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) {
return pThis->onReceive(pSender, dwConnID, pData, iLength);
}
static En_HP_HandleResult __HP_CALL
OnClose(HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) {
return pThis->onClose(pSender, dwConnID, enOperation, iErrorCode);
}
static En_HP_HandleResult __HP_CALL OnShutdown(HP_Server pSender) {
return pThis->onShutdown(pSender);
}
private:
static packServer *pThis;
HP_TcpPackServer m_pServer;
HP_TcpServerListener m_pListener;
};
template
packServer *packServer::pThis = nullptr;
/**
* pack类型客户端基础类
* @tparam T
* @tparam IP_0
* @tparam IP_1
* @tparam IP_2
* @tparam IP_3
* @tparam PORT
* @tparam MAX_PACKSIZE
* @tparam PACKHEADER_FLAG
*/
template
class packClient : public clientBase, public packClientListener {
public:
packClient() : clientBase(&m_pClient) {
pThis = this;
m_pListener = Create_HP_TcpPackClientListener();
m_pClient = Create_HP_TcpPackClient(m_pListener);
HP_Set_FN_Client_OnConnect(m_pListener, OnConnect);
HP_Set_FN_Client_OnSend(m_pListener, OnSend);
HP_Set_FN_Client_OnReceive(m_pListener, OnReceive);
HP_Set_FN_Client_OnClose(m_pListener, OnClose);
HP_TcpPackClient_SetMaxPackSize(m_pClient, MAX_PACKSIZE);
HP_TcpPackClient_SetPackHeaderFlag(m_pClient, PACKHEADER_FLAG);
}
~packClient() {
Destroy_HP_TcpPackClientListener(m_pListener);
Destroy_HP_TcpPackClient(m_pClient);
}
private:
static En_HP_HandleResult __HP_CALL OnConnect(HP_Client pSender, HP_CONNID dwConnID) {
return pThis->onConnect(pSender, dwConnID);
}
static En_HP_HandleResult __HP_CALL OnSend(HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) {
return pThis->onSend(pSender, dwConnID, pData, iLength);
}
static En_HP_HandleResult __HP_CALL
OnReceive(HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) {
return pThis->onReceive(pSender, dwConnID, pData, iLength);
}
static En_HP_HandleResult __HP_CALL
OnClose(HP_Client pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) {
return pThis->onClose(pSender, dwConnID, enOperation, iErrorCode);
}
protected:
static packClient *pThis;
HP_TcpPackClient m_pClient;
HP_TcpPackClientListener m_pListener;
};
template
packClient *packClient::pThis = nullptr;
#endif //HP_WRAPPER_HPP
//
// Created by Yoo on 2020/5/26.
//
#ifndef TEST_0_MYPACKCLIENT_HPP
#define TEST_0_MYPACKCLIENT_HPP
#include "hp_wrapper.hpp"
#include
class mypackclient : public packClient {
public:
mypackclient() {
beginReconnect();
}
~mypackclient() {
endReconnect();
}
private:
void beginReconnect() {
t = std::thread([this] {
while (!exit) {
if (HP_Client_GetState(m_pClient) == SS_STOPPED) {
start();
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
}
void endReconnect() {
exit = true;
if (t.joinable()) {
t.join();
}
}
virtual En_HP_HandleResult onConnect(HP_Client pSender, HP_CONNID dwConnID) override {
SetPkgInfo(pSender);
return HR_OK;
}
virtual En_HP_HandleResult onSend(HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) override {
return HR_OK;
}
virtual En_HP_HandleResult
onReceive(HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) override {
auto pInfo = FindPkgInfo(pSender);
if (pInfo != nullptr) {
std::cout << (char *) pData << std::endl;
}
return HR_OK;
}
virtual En_HP_HandleResult
onClose(HP_Client pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) override {
RemovePkgInfo(pSender);
return HR_OK;
}
private:
bool exit = false;
std::thread t;
};
#endif //TEST_0_MYPACKCLIENT_HPP
//
// Created by Yoo on 2020/5/26.
//
#ifndef TEST_0_MYPACKSERVER_HPP
#define TEST_0_MYPACKSERVER_HPP
#include "hp_wrapper.hpp"
#include
class Info{
public:
Info(){
memset(buffer,0,64);
}
void setBuffer(char *buf,int bufsize){
if(bufsize <= 64){
memcpy(buffer,buf,bufsize);
}
}
char * getBuffer(){
return buffer;
}
private:
char buffer[64];
};
class mypackserver : public packServer{
public:
mypackserver(){
start();
}
private:
virtual En_HP_HandleResult onPrepareListen(HP_Server pSender, SOCKET soListen) override {
return HR_OK;
}
virtual En_HP_HandleResult onAccept(HP_Server pSender, HP_CONNID dwConnID, SOCKET soClient) override{
SetPkgInfo(pSender,dwConnID);
return HR_OK;
}
virtual En_HP_HandleResult onSend(HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) override{
return HR_OK;
}
virtual En_HP_HandleResult onReceive(HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) override{
Info *pInfo = FindPkgInfo(pSender,dwConnID);
if(pInfo != nullptr){
std::cout << reinterpret_cast(pData) << std::endl;
std::cout << iLength << std::endl;
}
return HR_OK;
}
virtual En_HP_HandleResult
onClose(HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) override{
RemovePkgInfo(pSender,dwConnID);
return HR_OK;
}
virtual En_HP_HandleResult onShutdown(HP_Server pSender) override{
return HR_OK;
}
};
#endif //TEST_0_MYPACKSERVER_HPP
#include "mypackserver.hpp"
#include "mypackclient.hpp"
int main() {
mypackserver my;
mypackclient mc;
while (true){
std::string str;
std::getline(std::cin,str);
if(str == "exit"){
break;
}else{
mc.sendPack((BYTE*)str.c_str(),str.length()+1);
}
}
return 0;
}