文件:tcpthreadsocket.h

#ifndef TCPTHREADSOCKET_H
#define TCPTHREADSOCKET_H

#include "itcpsocket.h"

#include <QTcpSocket>
#include <QThread>

class TcpThreadSocket : public QObject
{
    Q_OBJECT
public:
    explicit TcpThreadSocket(qintptr socketDescriptor);
    ~TcpThreadSocket();

    void setITcpSocket(ITcpSocket*);

    void start();
    void quit();

protected:
    QThread *m_thread          = nullptr;
    QTcpSocket *m_socket       = nullptr;
    qintptr m_socketDescriptor = 0;
    ITcpSocket *m_iTcpSocket   = nullptr;

signals:
    void sig_connected(TcpThreadSocket *obj);
    void sig_disconnected(TcpThreadSocket *obj);

protected slots:
    void tmain();
    void slot_disconnected();
    void slot_readyRead();
};

#endif // TCPTHREADSOCKET_H

文件:tcpthreadsocket.cpp

#include "tcpthreadsocket.h"

TcpThreadSocket::TcpThreadSocket(qintptr socketDescriptor)
    : m_thread(new QThread), m_socketDescriptor(socketDescriptor)
{
    moveToThread(m_thread);

    connect(m_thread, SIGNAL(started()), this, SLOT(tmain()));
}

TcpThreadSocket::~TcpThreadSocket()
{
    m_thread->quit();
    m_thread->wait();

    if (m_socket)
        m_socket->close();

    delete m_thread;
    delete m_socket;
}

void TcpThreadSocket::setITcpSocket(ITcpSocket *itcpsocket)
{
    m_iTcpSocket = itcpsocket;
}

void TcpThreadSocket::start()
{
    m_thread->start();
}

void TcpThreadSocket::quit()
{
    if (m_socket)
        m_socket->close();
}

void TcpThreadSocket::tmain()
{
    m_socket = new QTcpSocket;
    if (m_socket != nullptr)
    {
        connect(m_socket, SIGNAL(disconnected()), this, SLOT(slot_disconnected()));
        connect(m_socket, SIGNAL(readyRead()), this, SLOT(slot_readyRead()));

        if (m_socket->setSocketDescriptor(m_socketDescriptor))
        {
            if (m_iTcpSocket != nullptr)
            {
                m_socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
                m_iTcpSocket->connected(*m_socket);
            }

            emit sig_connected(this);
            return;
        }
    }

    slot_disconnected();
}

void TcpThreadSocket::slot_disconnected()
{
    if (m_iTcpSocket != nullptr)
    {
        m_iTcpSocket->disconnected(*m_socket);
    }

    emit sig_disconnected(this);
}

void TcpThreadSocket::slot_readyRead()
{
    if (m_iTcpSocket != nullptr)
    {
        m_iTcpSocket->readyRead(*m_socket);
    }
}

文件:tcpserversocket.h

#ifndef TCPSERVERSOCKET_H
#define TCPSERVERSOCKET_H

#include "tcpthreadsocket.h"
#include "itcpsocket.h"

#include <QTcpServer>
#include <QList>

class TcpServerSocket : public QTcpServer
{
    Q_OBJECT

public:
    ~TcpServerSocket();
    static TcpServerSocket *getNewInstance(QObject *parent = nullptr);
    bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
    void setITcpSocket(ITcpSocket*);

private:
    explicit TcpServerSocket(QObject *parent = nullptr);
    void incomingConnection(qintptr socketDescriptor);

private:
    static TcpServerSocket *m_instance;
    QList<TcpThreadSocket*> m_tcpThreadList;
    ITcpSocket *m_iTcpSocket = nullptr;

private slots:
    void slot_connected(TcpThreadSocket *obj);
    void slot_disconnected(TcpThreadSocket *obj);
};

#endif // TCPSERVERSOCKET_H

文件:tcpserversocket.cpp

#include "tcpserversocket.h"

TcpServerSocket *TcpServerSocket::m_instance = nullptr;

TcpServerSocket::TcpServerSocket(QObject *parent)
{
    Q_UNUSED(parent)
}

TcpServerSocket *TcpServerSocket::getNewInstance(QObject *parent)
{
    if (m_instance == nullptr)
    {
        m_instance = new TcpServerSocket(parent);
    }

    return m_instance;
}

bool TcpServerSocket::listen(const QHostAddress &address, quint16 port)
{
    return this->QTcpServer::listen(address, port);
}

void TcpServerSocket::setITcpSocket(ITcpSocket *itcpsocket)
{
    m_iTcpSocket = itcpsocket;
}

void TcpServerSocket::incomingConnection(qintptr socketDescriptor)
{
    TcpThreadSocket *pThread = new TcpThreadSocket(socketDescriptor);

    if (pThread != nullptr)
    {
        pThread->setITcpSocket(m_iTcpSocket);

        connect(pThread, SIGNAL(sig_connected(TcpThreadSocket *)), this, SLOT(slot_connected(TcpThreadSocket *)));
        connect(pThread, SIGNAL(sig_disconnected(TcpThreadSocket *)), this, SLOT(slot_disconnected(TcpThreadSocket *)));

        pThread->start();
    }
}

void TcpServerSocket::slot_connected(TcpThreadSocket *obj)
{
    m_tcpThreadList.push_front(obj);
}

void TcpServerSocket::slot_disconnected(TcpThreadSocket *obj)
{
    m_tcpThreadList.removeOne(obj);

    delete obj;
}

TcpServerSocket::~TcpServerSocket()
{
    for(auto pThread : m_tcpThreadList)
        delete pThread;
}

[接口类] 文件:itcpsocket.h

#ifndef ITCPSOCKET_H
#define ITCPSOCKET_H

#include <QTcpSocket>

class ITcpSocket
{
public:
    virtual void connected(QTcpSocket &socket) = 0;
    virtual void disconnected(const QTcpSocket &socket) = 0;
    virtual void readyRead(QTcpSocket &socket) = 0;
    virtual ~ITcpSocket() = default;
};

#endif // ITCPSOCKET_H

[接口实现 , 自定义数据处理] 文件:tcpsocketmsgdeal.h

#ifndef TCPSOCKETMSGDEAL_H
#define TCPSOCKETMSGDEAL_H

#include "itcpsocket.h"

#include <QObject>

class TcpSocketMsgDeal : public ITcpSocket
{
public:
    TcpSocketMsgDeal(QObject *parent = nullptr);

private:
    int socket_num = 0;

    void connected(QTcpSocket &socket) override;
    void disconnected(const QTcpSocket &socket) override;
    void readyRead(QTcpSocket &socket) override;
};

#endif // TCPSOCKETMSGDEAL_H

文件:tcpsocketmsgdeal.cpp

#include "tcpsocketmsgdeal.h"

#include <QThread>
#include <QtNetwork>

#include <QDebug>

TcpSocketMsgDeal::TcpSocketMsgDeal(QObject *parent)
{
    Q_UNUSED(parent)
}

void TcpSocketMsgDeal::connected(QTcpSocket &socket)
{
    qDebug() << "------------------------------";
    qDebug() << "connected : ";
    qDebug() << "current thread id : " << QThread::currentThreadId();
    qDebug() << socket.peerAddress();
    qDebug() << socket.peerPort();
    qDebug() << "Link num: " << ++socket_num;
}

void TcpSocketMsgDeal::disconnected(const QTcpSocket &socket)
{
    qDebug() << "------------------------------";
    qDebug() << "disconnected : ";
    qDebug() << "current thread id : " << QThread::currentThreadId();
    qDebug() << socket.peerAddress();
    qDebug() << socket.peerPort();
    qDebug() << "Link num: " << --socket_num;
}

void TcpSocketMsgDeal::readyRead(QTcpSocket &socket)
{
    qDebug() << socket.readAll();
}

文件:main.cpp

#include <QCoreApplication>

#include "tcpserversocket.h"
#include "tcpsocketmsgdeal.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    TcpSocketMsgDeal *msgDeal = new TcpSocketMsgDeal();
    TcpServerSocket *server   = TcpServerSocket::getNewInstance();  // 单例
    server->setITcpSocket(msgDeal);                                 // 数据处理对象
    server->listen(QHostAddress::Any, 8888);                        // 网络参数

    return a.exec();
}

输出:

------------------------------
connected :
current thread id :  0x21a8
QHostAddress("::ffff:192.168.3.28")
8782
Link num:  1
------------------------------
connected :
current thread id :  0x10e4
QHostAddress("::ffff:192.168.3.28")
8783
Link num:  2
------------------------------
disconnected :
current thread id :  0x10e4
QHostAddress("::ffff:192.168.3.28")
8783
Link num:  1
------------------------------
disconnected :
current thread id :  0x21a8
QHostAddress("::ffff:192.168.3.28")
8782
Link num:  0

主要功能:

  1. 网络管理与消息处理分离。
  2. 网连接断开,socket 线程对象主动销毁;

TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧