Qt的Tcp服务器多线程编程-附带代码展示

Qt的Tcp服务器多线程编程-附带代码展示

该程序主要实现tcp服务器如何使用多线程的方式来连接多个客户端,此文章没有实现客户端的多线程编程。
创建子线程时需要注意的点:
1、子线程与主线程之间交互数据时,应采用信号槽的方式
2、子线程中实例化的对象,不应出现在其他线程当中
3、子线程需加入QThread::exec()事件循环函数
4、子线程的销毁关联窗口的销毁信号,调用exit()、quit()、deleteLater()
期间所遇到的问题:
1、之前的思路是想在子线程当中去监听客户端的连接以及数据处理,后面发现在子线程中关联的readyRead()信号始终无法接收到,随后改为在主线程中监听客户端的连接,在子线程中只处理数据
2、子线程对象的实例化也需要注意,需在newConnection()连接的槽函数进行连接,否则客户端断开与服务端的连接后,再次连接时可能无法通信

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "mytcpserver.h"
#include <QTcpServer>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  MainWindow(QWidget *parent = nullptr);
  ~MainWindow();

  myTcpServer *mytcp_t;
  QTcpServer *server;

  QTcpServer *server_com2;
  tcp_server1 *mytcp_com2;
  int port;

private:
  Ui::MainWindow *ui;

private slots:
  void on_bt_listen_clicked();

};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QNetworkInterface>

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
  , ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  foreach (QHostAddress info, QNetworkInterface::allAddresses()) {
      qDebug()<<info.toString();
      if(info.toString().size() == 12)
        {
          ui->ld_severip->setText(info.toString());
        }
  }

}

MainWindow::~MainWindow()
{
  delete ui;
}


void MainWindow::on_bt_listen_clicked()
{

  qDebug()<<QString::fromLocal8Bit("主线程地址:")<<QThread::currentThreadId();

  port = ui->ld_port->text().toShort();

  //实例服务器对象
  server = new QTcpServer();
  server_com2 = new QTcpServer();
  //监听端口
  server->listen(QHostAddress::Any, port);
  server_com2->listen(QHostAddress::Any, port+2);
  //连接新连接信号,关联线程的启动
  connect(server, &QTcpServer::newConnection, this, [=]{
      mytcp_t = new myTcpServer(server);
      //启动子线程
      mytcp_t->start();
    });
  connect(server_com2, &QTcpServer::newConnection, this, [=]{
      mytcp_com2 = new tcp_server1(server_com2);
      mytcp_com2->start();
    });
  //线程的销毁
  connect(this, &MainWindow::destroyed, this, [=]{
      mytcp_t->exit();
      mytcp_t->quit();
      mytcp_t->deleteLater();

      mytcp_com2->exit();
      mytcp_com2->quit();
      mytcp_com2->deleteLater();
    });

}

mytcpserver.h

#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H

#include <QTcpServer>
#include <QTcpSocket>
#include <QThread>

#include "dataprocess.h"

class myTcpServer: public QThread
{
  Q_OBJECT
public:
  explicit myTcpServer(QTcpServer *parent);

  void run() override;

private:

  void WriteCmd(int _cmd);

signals:

protected:
  QTcpServer *server;
  QTcpSocket *socket;
  QString rcv;

  dataprocess *anysis_data;

public slots:
  void getAddrlist(QStringList addr_list);

};

class tcp_server1: public QThread
{
  Q_OBJECT
public:
  explicit tcp_server1(QTcpServer *parent);

  void run() override;

protected:
  QTcpServer *server;
  QTcpSocket *socket;
  QString rcv;

};

#endif // MYTCPSERVER_H

mytcpserver.cpp

#include "mytcpserver.h"
#include <QDebug>
#include <QThread>
QString cmd_reset = "AT+RESET\r\n";

myTcpServer::myTcpServer(QTcpServer *parent)
{
  server = parent;
}

void myTcpServer::run()
{

      bool res = false;
      qDebug()<<QStringLiteral("子线程地址:")<<QThread::currentThreadId();

      socket = new QTcpSocket();
      socket = server->nextPendingConnection();

      anysis_data = new dataprocess;

      res = connect(socket, &QTcpSocket::readyRead, [=](){
          int cnt = 0;
          rcv = socket->readAll();
          //DataAnysis(rcv);
          cnt = anysis_data->DataAnysis(rcv);
          WriteCmd(cnt);
          qDebug()<<"have already receive data";
      });
      connect(socket, &QTcpSocket::disconnected, [=](){
          qDebug()<<"Disconnected";
        });
      qDebug()<<res;

      // 进入事件循环
      exec();
}


void myTcpServer::WriteCmd(int _cmd)
{
  switch(_cmd)
  {
      case 1:
        break;
      case 2:
        break;
      case 3:
        break;
    }
}

void myTcpServer::getAddrlist(QStringList addr_list)
{
  qDebug()<<addr_list[0];
}






tcp_server1::tcp_server1(QTcpServer *parent)
{
  server = parent;
}

void tcp_server1::run()
{
  bool res = false;
  qDebug()<<QStringLiteral("子线程地址:")<<QThread::currentThreadId();

  socket = new QTcpSocket();

  socket = server->nextPendingConnection();

  res = connect(socket, &QTcpSocket::readyRead, [=](){
      rcv = socket->readAll();
      //DataAnysis(rcv);
      qDebug()<<"have already receive data";
  });
  connect(socket, &QTcpSocket::disconnected, [=](){
      qDebug()<<"Disconnected";
    });
  qDebug()<<res;

  // 进入事件循环
  exec();
}

dataprocess.h

#ifndef DATAPROCESS_H
#define DATAPROCESS_H

#include <QObject>
#include <QString>
#include <QTcpSocket>


class dataprocess: public QObject
{
  Q_OBJECT
public:
  explicit dataprocess();
  //~dataprocess();

  int DataAnysis(QString str);

private:
  QTcpSocket *socket;
  QStringList strlist;

signals:
  void moveAddrlist(QStringList addrlist);

};

#endif // DATAPROCESS_H

dataprocess.cpp

#include "dataprocess.h"

dataprocess::dataprocess()
{

}

int dataprocess::DataAnysis(QString str)
{
    if(str == "AT-RESET:OK\r\n")
    {
        qDebug()<<"Module Init Success";
    }
    else if(str == "AT-LOGO:BT11P31\r\n")
    {
        qDebug()<<"Init output Success";
    }
    else if(str == "AT-SSCANN:OK\r\n")
    {
        qDebug()<<"Scann cmd send";
    }
    else if(str.contains("AT-SCANI:OK"))
    {

    }
    else if(str.contains(QString("AT-SCANRP:")))
    {
        strlist.push_back(str.mid(10, 12));
        emit moveAddrlist(strlist);
        qDebug()<<strlist[0];
    }
    else
    {

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值