mingw 使用 HPSocket 进阶版

#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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值