Linux下 C++ HPSocket通信框架的簡單使用


HPSocket  -- 文檔和下載地址 :https://www.oschina.net/p/hp-socket

 

HPSocket  -- Github :https://github.com/ldcsaa/HP-Socket

源碼文檔案例可在交流群下載:QQ-75375912

 

* 本篇講解的是TcpServer的使用 *

 

環境Ubuntu 18.04.3     編輯工具IDE QT5.13.2

在群里可以下載相關源碼目錄如下

 

我們需要的是Linux目錄下的東西 將里面的東西都復制到Linux系統內

鑒於我們是簡單利用TCP 開發Server 我們只需要

include,lib不過良心的作者為我們做了個install.sh和compile.sh

安裝如下:

 

 

 

include和lib會安裝在 /usr/local/include 和  /usr/local/lib64  兩個目錄下 

打開Qt Creator 新建一個項目 Qt Widgets Application 命名為HpSocketDemo

更改Pro文件如下:

 

 

 

新建類MyTcpListener 包含頭文件hpsocket/HPSocket.h  繼承CTcpServerListener

將MyTcpListener變成單例類,再加上自己實現的事件回調類ISocketView 代碼如下:

#ifndef ISOCKETVIEW_H
#define ISOCKETVIEW_H


//此處僅當教程使用 具體回傳參數由各位根據需求來定

class ISocketView
{
public:
    virtual void onPrepareListen()=0;
    virtual void onAccept()=0;
    virtual void onHandShake() = 0;
    virtual void onReceive()=0;
    virtual void onSend()=0;
    virtual void onShutdown()=0;
    virtual void onClose()=0;
};
#endif // ISOCKETVIEW_H

 

Server執行順序如下:

執行startServer()  導致 OnPrepareListen觸發   可進行發送數據的行為

外部Client接入連接 導致onAccept觸發    可進行接受數據的行為 

外部Client發送數據 導致onReceive觸發

外部Client斷開連接導致onClose觸發  

執行stopServer() 導致onClose onShutdown 觸發 

 

#ifndef MYTCPLISTENER_H
#define MYTCPLISTENER_H

#include "hpsocket/HPSocket.h"
#include "ISocketView.h"
#include <QMutex>
#include <QMutexLocker>

//這個類的需求請自行添加
class MySocketBuffer
{
public:
    static MySocketBuffer* newBuffer(){ return new MySocketBuffer();}
    MySocketBuffer(){}
};



class MyTcpListener:CTcpServerListener
{

public:
    static MyTcpListener* getInstance();
    CTcpPackServerPtr mServer;

    //1.開啟服務器
    bool startServer();

    //2.關閉服務器
    bool stopServer();


    void registerView(ISocketView* view);
    void unRegisterView();
public:
    //監聽成功時觸發
    EnHandleResult OnPrepareListen(ITcpServer *pSender, SOCKET soListen);

    //接受到連接時觸發
    EnHandleResult OnAccept(ITcpServer *pSender, CONNID dwConnID, UINT_PTR soClient);

    //握手成功時觸發
    EnHandleResult OnHandShake(ITcpServer *pSender, CONNID dwConnID);

    //收到數據時觸發
    EnHandleResult OnReceive(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength);

    //發送數據成功觸發
    EnHandleResult OnSend(ITcpServer *pSender, CONNID dwConnID, const BYTE *pData, int iLength);

    //服務器關閉時觸發
    EnHandleResult OnShutdown(ITcpServer *pSender);

    //關閉某個連接時觸發
    EnHandleResult OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode);
private:
    ISocketView *mView;
private:
    //單例實現
    MyTcpListener();
    MyTcpListener(const MyTcpListener&);
    MyTcpListener& operator=(const MyTcpListener&);
    virtual ~MyTcpListener();
    class CGarbo                    //
    {
    public:
        CGarbo(){}
        ~CGarbo()
        {
            if (MyTcpListener::mServerListener)
            {
                delete MyTcpListener::mServerListener;
            }
        }
    };
    static CGarbo mCGarbo;
private:
    static MyTcpListener* mServerListener;
    static QMutex mMutex;
};

#endif // MYTCPLISTENER_H

 

#include "MyTcpListener.h"


MyTcpListener* MyTcpListener::mServerListener=nullptr;
QMutex MyTcpListener::mMutex;


MyTcpListener::MyTcpListener()
    :mServer(this)//要想監聽生效 這個必須傳入監聽者對象
    ,mView(nullptr)
{

}


MyTcpListener::~MyTcpListener()
{
 
}

MyTcpListener *MyTcpListener::getInstance()
{
    MyTcpListener* tmp = mServerListener;
    if (tmp == nullptr)
    {
        QMutexLocker locker(&mMutex);
        tmp = mServerListener;
        if (tmp == nullptr)
        {
            tmp = new MyTcpListener();
            mServerListener = tmp;
        }
    }
    return mServerListener;
}

bool MyTcpListener::startServer()
{
    //mServer ->SetSocketBufferSize(2048);

    return mServer->Start("0,0,0,0",12000);
}

bool MyTcpListener::stopServer()
{
    return mServer->Stop();
}

void MyTcpListener::registerView(ISocketView *view)
{
    mView = view;
}

void MyTcpListener::unRegisterView()
{
    mView=nullptr;
}

EnHandleResult MyTcpListener::OnPrepareListen(ITcpServer *pSender, SOCKET soListen)
{
    //回調觸發 注意不能直接改UI Qt建議采用信號槽
    if(mView!=nullptr)
    {
        mView->onPrepareListen();
    }

    //獲取監聽的ip port信息
    TCHAR lpszAddress[30];
    int iAddressLen;
    USHORT unPort;
    pSender->GetListenAddress(lpszAddress,iAddressLen,unPort);

    return HR_OK;
}

EnHandleResult MyTcpListener::OnAccept(ITcpServer *pSender, CONNID dwConnID, UINT_PTR soClient)
{
    //回調觸發 注意不能直接改UI Qt建議采用信號槽
    if(mView!=nullptr)
    {
        mView->onAccept();
    }

    //為每一個新接入的連接 附加一個對象 因為我們是根據ID來區分連接的
    pSender->SetConnectionExtra(dwConnID,MySocketBuffer::newBuffer());


    return HR_OK;
}

EnHandleResult MyTcpListener::OnHandShake(ITcpServer *pSender, CONNID dwConnID)
{
    //回調觸發 注意不能直接改UI Qt建議采用信號槽
    if(mView!=nullptr)
    {
        mView->onHandShake();
    }

    return HR_OK;
}

EnHandleResult MyTcpListener::OnReceive(ITcpServer *pSender, CONNID dwConnID, const BYTE *pData, int iLength)
{

    //特別注意這個回調觸發的方式   當同一個ID觸發時是按照順序觸發
    //如果是不同ID觸發則是線程觸發 所以在這里不能做阻塞處理
    //特別是不能加鎖做同步處理
    //如果想高速處理數據 請采用線程池方式

    //回調觸發 注意不能直接改UI Qt建議采用信號槽
    if(mView!=nullptr)
    {
        mView->onReceive();
    }

    //這里就可以采用Accept時附加的對象做處理,比如定義方法 數據緩存等
    MySocketBuffer * pSocketBuffer=nullptr;
    pSender->GetConnectionExtra(dwConnID,(PVOID*)pSocketBuffer);

    if(pSocketBuffer!=nullptr)
    {
        //可在此對pSocketBuffer做操作
    }

    return HR_OK;
}



EnHandleResult MyTcpListener::OnSend(ITcpServer *pSender, CONNID dwConnID, const BYTE *pData, int iLength)
{
    //回調觸發 注意不能直接改UI Qt建議采用信號槽
    if(mView!=nullptr)
    {
        mView->onSend();
    }


    return HR_OK;
}

EnHandleResult MyTcpListener::OnShutdown(ITcpServer *pSender)
{
    //回調觸發 注意不能直接改UI Qt建議采用信號槽
    if(mView!=nullptr)
    {
        mView->onShutdown();
    }


    return HR_OK;
}

EnHandleResult MyTcpListener::OnClose(ITcpServer *pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
    //回調觸發 注意不能直接改UI Qt建議采用信號槽
    if(mView!=nullptr)
    {
        mView->onClose();
    }

    //當一個連接關閉時 我們需要自己將onAccept 時 new出來的對象delete掉
    MySocketBuffer * pSocketBuffer=nullptr;
    pSender->GetConnectionExtra(dwConnID,(PVOID*)pSocketBuffer);
    if(pSocketBuffer!=nullptr){ delete pSocketBuffer;}

    return HR_OK;
}

 

一個簡單的TCP服務器就搭建好了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM