IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 基于QT的tcp server设计 -> 正文阅读

[网络协议]基于QT的tcp server设计

基于Qt,设计了一个tcp server,主要用到:

  • QTcpServer
  • QTcpSocket
  • QThread

UML 类图

TcpServer构造函数:

TcpServer(QString t_server_name,quint32 t_thread_cout,msgHandle t_func=nullptr,QObject *parent = nullptr);
  • t_server_name:服务名字
  • t_thread_cout:支持处理socket的子线程个数
  • t_func:消息处理函数,其类型如下:
    • typedef std::function<void (QByteArray &msg,QTcpSocket* sock)> msgHandle;

TcpServer启动函数:

void startListen(quint16 t_port);
  • t_port:服务端口

tcpserver.h

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include "tcpsocket.h"

#include <QObject>
#include <QTcpServer>
#include <QString>
#include <QThread>
#include <QVector>

struct SocketInfo
{
    quint32 socket_num;
    QThread socket_thread;
};

class TcpServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit TcpServer(QString t_server_name,quint32 t_thread_cout,msgHandle t_func=nullptr,QObject *parent = nullptr);
    ~TcpServer();

    QString getServerName();
    quint16 getServerPort();

public slots:
    void setMsgHandle(msgHandle t_func);
    void startListen(quint16 t_port);
    void stopListen();
    void socketClose(qint32 t_id);

protected:
    void incomingConnection(qintptr socketDescriptor);
    qint32 getMinSocketThread();

private:
    QString m_server_name;
    quint16 m_port;

    quint32 m_thread_count;
    QVector<SocketInfo*> m_thread_vec;
    msgHandle m_func;
};

#endif // TCPSERVER_H

tcpserver.cpp

#include "tcpserver.h"

#include <QByteArray>
#include <QHostAddress>
#include <QNetworkProxyFactory>
#include <QDebug>

TcpServer::TcpServer(QString t_server_name,quint32 t_thread_cout,msgHandle t_func,QObject *parent) :
    QTcpServer(parent),
    m_server_name(t_server_name),
    m_thread_count(t_thread_cout),
    m_func(t_func)
{
    qDebug()<<__FILE__<<":"<<__LINE__<<":"<<"this server is:"<<t_server_name<<endl;
    this->m_port=0; 
    for(quint32 index=0;index<this->m_thread_count;index++)
    {
        SocketInfo *tmp_info=new SocketInfo();
        tmp_info->socket_num=0;
        tmp_info->socket_thread.start();
        this->m_thread_vec.append(tmp_info);
    }
}

TcpServer::~TcpServer()
{
    if(this->isListening())
    {
        this->close();
    }

    int cout=this->m_thread_vec.size();
    for(int index=0;index<cout;index++)
    {
        this->m_thread_vec[index]->socket_thread.terminate();
        this->m_thread_vec[index]->socket_thread.wait();
        delete this->m_thread_vec[index];
        this->m_thread_vec[index]=nullptr;
    }
}

QString TcpServer::getServerName()
{
    return this->m_server_name;
}

quint16 TcpServer::getServerPort()
{
    return this->m_port;
}

void TcpServer::setMsgHandle(msgHandle t_func)
{
    this->m_func=t_func;
}

void TcpServer::startListen(quint16 t_port)
{
    if(this->isListening())
    {
        this->close();
    }

    if(this->listen(QHostAddress::Any,t_port))
    {
        qDebug()<<__FILE__<<":"<<__LINE__<<":"<<"listen successful:"<<t_port<<endl;
        this->m_port=t_port;
    }
    else
    {
        qDebug()<<__FILE__<<":"<<__LINE__<<":"<<"listen failed:"<<t_port<<endl;
    }
}

void TcpServer::stopListen()
{
    qDebug()<<__FILE__<<":"<<__LINE__<<":"<<"stop listen: "<<this->m_port<<endl;
    if(this->isListening())
    {
        this->close();
    }
}

void TcpServer::incomingConnection(qintptr socketDescriptor)
{
    qDebug()<<__FILE__<<":"<<__LINE__<<":"<<"new connection: "<<socketDescriptor<<endl;
    qint32 cut_id=this->getMinSocketThread();

    TcpSocket *tmp_soc=new TcpSocket(cut_id,socketDescriptor,this->m_func);
    connect(tmp_soc,SIGNAL(socketClose(qint32)),this,SLOT(socketClose(qint32)));
    tmp_soc->moveToThread(&(this->m_thread_vec[cut_id]->socket_thread));
    this->m_thread_vec[cut_id]->socket_num++;
}

void TcpServer::socketClose(qint32 t_id)
{

    this->m_thread_vec[t_id]->socket_num--;
}

qint32 TcpServer::getMinSocketThread()
{
    qint32 tmp_id=0;
    qint32 th_cout=this->m_thread_vec.size();
    for(qint32 index=0;index<th_cout;index++)
    {
        if(this->m_thread_vec[index]->socket_num<this->m_thread_vec[tmp_id]->socket_num)
        {
            tmp_id=index;
        }
    }
    return tmp_id;
}

tcpsocket.h

#ifndef TCPSOCKET_H
#define TCPSOCKET_H

#include <QObject>
#include <QTcpSocket>
#include <QByteArray>
#include <QTimer>

#include <iostream>
#include <functional>

typedef std::function<void (QByteArray &msg,QTcpSocket* sock)> msgHandle;

class TcpSocket : public QTcpSocket
{
    Q_OBJECT
public:
    explicit TcpSocket(qint32 id,qintptr socketDescriptor,msgHandle t_msg_handle=nullptr,QObject *parent = nullptr);
    ~TcpSocket();

signals:
    void socketClose(qint32);

public slots:
    void msgTimeout();
    void readMessage();
    void socketErr(QAbstractSocket::SocketError tError);
    void socketdisconnect();

private:
    qint32 m_id;
    msgHandle m_msg_handle;

    QTimer *m_msg_timeout;
};

#endif // TCPSOCKET_H

tcpsocket.cpp

#include "tcpsocket.h"

#include <QByteArray>
#include <QHostAddress>
#include <QDebug>

static const qint32 TIMEOUT_VALUE=30000;

TcpSocket::TcpSocket(qint32 id,qintptr socketDescriptor,msgHandle t_msg_handle,QObject *parent) :
    QTcpSocket(parent),
    m_id(id),
    m_msg_handle(t_msg_handle)
{
    m_msg_timeout =new QTimer(this);
    connect(this->m_msg_timeout,SIGNAL(timeout()),this,SLOT(msgTimeout()));
    this->setSocketDescriptor(socketDescriptor);
    connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketErr(QAbstractSocket::SocketError)));
    connect(this,SIGNAL(disconnected()),this,SLOT(socketdisconnect()));
    connect(this, SIGNAL(readyRead()), this, SLOT(readMessage()));

    this->m_msg_timeout->start(TIMEOUT_VALUE);
}

TcpSocket::~TcpSocket()
{
    this->disconnectFromHost();
}

void TcpSocket::msgTimeout()
{
    qDebug()<<__FILE__<<":"<<__LINE__<<":"<<"socket connect free timeout"<<endl;
    this->disconnectFromHost();
}

void TcpSocket::readMessage()
{
    this->m_msg_timeout->stop();
    QByteArray t_message=this->readAll();
    if(this->m_msg_handle!=nullptr)
    {
        m_msg_handle(t_message,this);
    }

    this->m_msg_timeout->start(TIMEOUT_VALUE);
}

void TcpSocket::socketErr(QAbstractSocket::SocketError tError)
{
    qDebug()<<__FILE__<<":"<<__LINE__<<":"<<"id: "<<this->socketDescriptor()<<"socket error: "<<this->errorString()<<endl;
    switch (tError)
    {
    case QAbstractSocket::RemoteHostClosedError:
        this->disconnectFromHost();
        break;
    default:
        this->disconnectFromHost();
        break;
    }
}

void TcpSocket::socketdisconnect()
{
    emit socketClose(this->m_id);
    this->deleteLater();
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-05 20:29:39  更:2021-07-05 20:29:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:44:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码