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下 C++ HPSocket通信框架的简单使用

 

我们需要的是Linux目录下的东西 将里面的东西都复制到Linux系统内

鉴于我们是简单利用TCP 开发Server 我们只需要

include,lib不过良心的作者为我们做了个install.sh和compile.sh

安装如下:

Linux下 C++ HPSocket通信框架的简单使用

 

 

 

include和lib会安装在 /usr/local/include 和  /usr/local/lib64  两个目录下 

打开Qt Creator 新建一个项目 Qt Widgets Application 命名为HpSocketDemo

更改Pro文件如下:

Linux下 C++ HPSocket通信框架的简单使用

 

 

 

新建类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服务器就搭建好了

原文链接: https://www.cnblogs.com/tian11shiyi/p/12461201.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    Linux下 C++ HPSocket通信框架的简单使用

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/334754

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午9:48
下一篇 2023年3月1日 下午9:49

相关推荐