#ifndef HPSOCKET4CWRAPPER_HPP
#define HPSOCKET4CWRAPPER_HPP
#include <cstdio>
#include <shared_mutex>
#include <optional>
#include <map>
#include <HPSocket4C.h>
/**
* 如果 lambda 表达式不捕获任何外部变量,在特定的情况下,会有额外的代码生成。
* 其中,特定情况是指:有 lambda_xxxx 类 到 函数指针 的类型转换
*/
template <typename T,typename V>
class VirtualTable{
using mutex = std::shared_mutex;
using lock_r = std::shared_lock<mutex>;
using lock_w = std::unique_lock<mutex>;
public:
bool add(const T& t,const V& v){
lock_w lock(mtx);
auto it = vt.find(t);
if(it == vt.end()){
vt.emplace(t,v);
return true;
}
return false;
}
bool erase(const T& t){
lock_w lock(mtx);
auto it = vt.find(t);
if(it != vt.end()){
vt.erase(it);
return true;
}
return false;
}
template<typename C,typename R,typename ...Arg>
std::optional<R> doRead(R(C::*f)(T,Arg...),T t,Arg...arg){
lock_r lock(mtx);
auto it = vt.find(t);
if(it != vt.end()){
auto ptr = it->second;
return std::make_optional((ptr->*f)(t,arg...));
}
return std::nullopt;
}
private:
std::map<T,V> vt;
mutex mtx;
};
/**
* 服务端基础类
*/
template <typename Server,typename Listener>
class ServerBase{
public:
void setServer(Server server){
m_Server = server;
}
Server getServer() const{
return m_Server;
}
void setListener(Listener listener){
m_Listener = listener;
}
Listener getListener() const{
return m_Listener;
}
BOOL start(const char * ip,unsigned int port) {
return HP_Server_Start(m_Server, ip, port);
}
BOOL stop() {
return HP_Server_Stop(m_Server);
}
BOOL sendPack(HP_CONNID dwConnID, const BYTE *pBuffer, int iLength) {
return HP_Server_Send(m_Server, dwConnID, pBuffer, iLength);
}
BOOL sendPacks(HP_CONNID dwConnID, const WSABUF pBuffers[], int iCount) {
return HP_Server_SendPackets(m_Server, dwConnID, pBuffers, iCount);
}
En_HP_ServiceState state(){
return HP_Server_GetState(m_Server);
}
private:
Server m_Server;
Listener m_Listener;
};
/**
* 客户端基础类
*/
template <typename Client,typename Listener>
class ClientBase{
public:
void setClient(Client client){
m_Client = client;
}
Client getClient() const{
return m_Client;
}
void setListener(Listener listener){
m_Listener = listener;
}
Listener getListener() const{
return m_Listener;
}
BOOL start(const char* m_IP,unsigned int PORT) {
return HP_Client_Start(m_Client, m_IP, PORT, TRUE);
}
BOOL stop() {
return HP_Client_Stop(m_Client);
}
BOOL sendPack(const BYTE *pBuffer, int iLength) {
return HP_Client_Send(m_Client, pBuffer, iLength);
}
BOOL sendPacks(const WSABUF pBuffers[], int iCount) {
return HP_Client_SendPackets(m_Client, pBuffers, iCount);
}
En_HP_ServiceState state(){
return HP_Client_GetState(m_Client);
}
private:
Client m_Client;
Listener m_Listener;
};
class TcpServer :public ServerBase<HP_TcpServer,HP_TcpServerListener>{
public:
TcpServer(){
setListener(Create_HP_TcpServerListener());
HP_Set_FN_Server_OnPrepareListen(getListener(), [](HP_UdpServer pSender, SOCKET soListen){
auto result = vt.doRead(&TcpServer::onPrepareListen,pSender,soListen);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnAccept(getListener(), [](HP_UdpServer pSender, HP_CONNID dwConnID, UINT_PTR pSockAddr){
auto result = vt.doRead(&TcpServer::onAccept,pSender,dwConnID,pSockAddr);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnSend(getListener(), [](HP_UdpServer pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength){
auto result = vt.doRead(&TcpServer::onSend,pSender,dwConnID,pData,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnReceive(getListener(), [](HP_UdpServer pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength){
auto result = vt.doRead(&TcpServer::onReceive,pSender,dwConnID,pData,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnClose(getListener(), [](HP_UdpServer pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode){
auto result = vt.doRead(&TcpServer::onClose,pSender,dwConnID,enOperation,iErrorCode);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnShutdown(getListener(), [](HP_UdpServer pSender){
auto result = vt.doRead(&TcpServer::onShutdown,pSender);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
setServer(Create_HP_TcpServer(getListener()));
vt.add(getServer(),this);
}
virtual ~TcpServer(){
vt.erase(getServer());
Destroy_HP_TcpServer(getServer());
Destroy_HP_TcpServerListener(getListener());
}
protected:
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;
private:
inline static VirtualTable<HP_TcpServer,TcpServer*> vt;
};
class TcpClient :public ClientBase< HP_TcpClient,HP_TcpClientListener>{
public:
TcpClient(){
HP_Set_FN_Client_OnConnect(getListener(), [](HP_Client pSender, HP_CONNID dwConnID){
auto result = vt.doRead(&TcpClient::onConnect,pSender,dwConnID);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
setListener(Create_HP_TcpClientListener());
HP_Set_FN_Client_OnSend(getListener(), [](HP_Client pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength){
auto result = vt.doRead(&TcpClient::onSend,pSender,dwConnID,pData,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Client_OnReceive(getListener(), [](HP_Client pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength){
auto result = vt.doRead(&TcpClient::onReceive,pSender,dwConnID,pData,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Client_OnClose(getListener(), [](HP_Client pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode){
auto result = vt.doRead(&TcpClient::onClose,pSender,dwConnID,enOperation,iErrorCode);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
setClient(Create_HP_TcpClient(getListener()));
vt.add(getClient(),this);
}
virtual ~TcpClient(){
vt.erase(getClient());
Destroy_HP_TcpClient(getClient());
Destroy_HP_TcpClientListener(getListener());
}
protected:
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;
private:
inline static VirtualTable<HP_TcpClient,TcpClient*> vt;
};
/**
* pull 服务端的类
*/
template <typename INFO>
class TcpPullServer :public ServerBase<HP_TcpPullServer,HP_TcpPullServerListener>{
public:
TcpPullServer(){
setListener(Create_HP_TcpPullServerListener());
HP_Set_FN_Server_OnPrepareListen(getListener(), [](HP_Server pSender, SOCKET soListen) {
auto result = vt.doRead(&TcpPullServer::onPrepareListen,pSender,soListen);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnAccept(getListener(), [](HP_Server pSender, HP_CONNID dwConnID, SOCKET soClient) {
auto result = vt.doRead(&TcpPullServer::onAccept,pSender,dwConnID,soClient);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnSend(getListener(), [](HP_Server pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) {
auto result = vt.doRead(&TcpPullServer::onSend,pSender,dwConnID,pData,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnPullReceive(getListener(), [](HP_Server pSender, HP_CONNID dwConnID, int iLength) {
auto result = vt.doRead(&TcpPullServer::onReceive,pSender,dwConnID,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnClose(getListener(), [](HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) {
auto result = vt.doRead(&TcpPullServer::onClose,pSender,dwConnID,enOperation,iErrorCode);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnShutdown(getListener(), [](HP_Server pSender) {
auto result = vt.doRead(&TcpPullServer::onShutdown,pSender);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
setServer(Create_HP_TcpPullServer(getListener()));
vt.add(getServer(),this);
}
virtual ~TcpPullServer() {
Destroy_HP_TcpPullServerListener(getListener());
Destroy_HP_TcpPullServer(getServer());
}
BOOL SetPkgInfo(HP_Server pSender, HP_CONNID dwConnID) {
return HP_Server_SetConnectionExtra(pSender, dwConnID, new INFO);
}
INFO *FindPkgInfo(HP_Server pSender, HP_CONNID dwConnID) {
PVOID pInfo = nullptr;
HP_Server_GetConnectionExtra(pSender, dwConnID, &pInfo);
return reinterpret_cast<INFO *>(pInfo);
}
void RemovePkgInfo(HP_Server pSender, HP_CONNID dwConnID) {
INFO *pInfo = FindPkgInfo(pSender, dwConnID);
if(pInfo != nullptr){
delete pInfo;
}
}
protected:
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;
private:
inline static VirtualTable<HP_TcpPullServer,TcpPullServer*> vt;
};
template <typename INFO>
class TcpPullClient :public ClientBase< HP_TcpPullClient,HP_TcpPullClientListener>{
public:
explicit TcpPullClient() {
setListener(Create_HP_TcpPullClientListener());
HP_Set_FN_Client_OnConnect(getListener(), [](HP_Client pSender, HP_CONNID dwConnID) {
auto result = vt.doRead(&TcpPullClient::onConnect,pSender,dwConnID);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Client_OnSend(getListener(), [](HP_Client pSender, HP_CONNID dwConnID, const BYTE *pData, int iLength) {
auto result = vt.doRead(&TcpPullClient::onSend,pSender,dwConnID,pData,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Client_OnPullReceive(getListener(), [](HP_Client pSender, HP_CONNID dwConnID, int iLength) {
auto result = vt.doRead(&TcpPullClient::onReceive,pSender,dwConnID,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Client_OnClose(getListener(), [](HP_Client pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode) {
auto result = vt.doRead(&TcpPullClient::onClose,pSender,dwConnID,enOperation,iErrorCode);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
setClient(Create_HP_TcpPullClient(getListener()));
vt.add(getClient(),this);
}
virtual ~TcpPullClient() {
vt.erase(getClient());
Destroy_HP_TcpPullClient(getClient());
Destroy_HP_TcpPullClientListener(getListener());
}
void SetPkgInfo(HP_Client pSender) {
HP_Client_SetExtra(pSender, new INFO);
}
INFO *FindPkgInfo(HP_Client pSender) {
PVOID pInfo = HP_Client_GetExtra(pSender);
return reinterpret_cast<INFO *>(pInfo);
}
void RemovePkgInfo(HP_Client pSender) {
INFO *pInfo = FindPkgInfo(pSender);
if(pInfo != nullptr){
delete pInfo;
}
}
protected:
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;
private:
inline static VirtualTable<HP_TcpPullClient,TcpPullClient*> vt;
};
class UdpServer :public ServerBase<HP_UdpServer,HP_UdpServerListener>{
public:
explicit UdpServer(){
setListener(Create_HP_UdpServerListener());
HP_Set_FN_Server_OnPrepareListen(getListener(), [](HP_UdpServer pSender, SOCKET soListen){
auto result = vt.doRead(&UdpServer::onPrepareListen,pSender,soListen);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnAccept(getListener(), [](HP_UdpServer pSender, HP_CONNID dwConnID, UINT_PTR pSockAddr){
auto result = vt.doRead(&UdpServer::onAccept,pSender,dwConnID,pSockAddr);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnSend(getListener(), [](HP_UdpServer pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength){
auto result = vt.doRead(&UdpServer::onSend,pSender,dwConnID,pData,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnReceive(getListener(), [](HP_UdpServer pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength){
auto result = vt.doRead(&UdpServer::onReceive,pSender,dwConnID,pData,iLength);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnClose(getListener(), [](HP_UdpServer pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode){
auto result = vt.doRead(&UdpServer::onClose,pSender,dwConnID,enOperation,iErrorCode);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
HP_Set_FN_Server_OnShutdown(getListener(), [](HP_UdpServer pSender){
auto result = vt.doRead(&UdpServer::onShutdown,pSender);
if(result.has_value()){
return result.value();
}
return HR_IGNORE;
});
setServer(Create_HP_UdpServer(getListener()));
vt.add(getServer(),this);
}
virtual ~UdpServer(){
vt.erase(getServer());
Destroy_HP_UdpServer(getServer());
Destroy_HP_UdpServerListener(getListener());
}
protected:
virtual En_HP_HandleResult onPrepareListen(HP_UdpServer pSender, SOCKET soListen) = 0;
virtual En_HP_HandleResult onAccept(HP_UdpServer pSender, HP_CONNID dwConnID, UINT_PTR pSockAddr)= 0;
virtual En_HP_HandleResult onSend(HP_UdpServer pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)= 0;
virtual En_HP_HandleResult onReceive(HP_UdpServer pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)= 0;
virtual En_HP_HandleResult onClose(HP_UdpServer pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode)= 0;
virtual En_HP_HandleResult onShutdown(HP_UdpServer pSender)= 0;
private:
inline static VirtualTable<HP_UdpServer,UdpServer*> vt;
};
using CTcpServer = TcpServer;
using CTcpClient = TcpClient;
template <typename INFO>
using CTcpPullServer = TcpPullServer<INFO>;
template <typename INFO>
using CTcpPullClient = TcpPullClient<INFO>;
using CUdpServer = UdpServer;
#endif // HPSOCKET4CWRAPPER_HPP
mingw 使用 HPSocket 进阶版
最新推荐文章于 2021-09-12 12:20:38 发布