ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

QT实现TCP通信

2022-03-06 12:32:27  阅读:130  来源: 互联网

标签:Widget QT thread void 通信 tcp ui TCP include


代码如下

tcp_thread.h

#ifndef TCP_THREAD_H
#define TCP_THREAD_H

#include <QThread>
#include <QHostAddress>
#include <QQueue>
#include <QMutex>
#include <QTcpSocket>
#include <QTcpServer>

class Tcp_Thread : public QThread
{
    Q_OBJECT
public:
    explicit Tcp_Thread(QHostAddress ip,QString port,QObject *parent = nullptr);
    ~Tcp_Thread();

    bool start_flag; //线程工作标志位
    bool connect_flag; //tcp连接标志位
    bool recv_flag; //保存接收数据到队列标志位
    QQueue<QByteArray> bytes_queue;
    QQueue<QString> msg_queue;

    QTcpSocket *socket; //套接字
    QTcpServer *server; //
    QHostAddress client_ip;
    qint16 client_port;
    bool c;

    void stop(); //暂停线程
    void go_on(); //继续线程
    void new_client_connect();

protected:
    void run();

signals:
    void signal_msg();
private:
    QMutex mutex; //互斥量,用来暂停和继续线程

private slots:
    void read_tcp();
    void socket_disconnect();

};

#endif // TCP_THREAD_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QHostAddress>
#include "tcp_thread.h"
#include<QTcpServer>
#include<QTcpSocket>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private:
    Ui::Widget *ui;
    Tcp_Thread *tcp_thread;

    QHostAddress get_local_host_ip();
    void is_ui_visiable(bool state);

private slots:
    void close_thread();
    void display_udp_frame();
    void print_tcp_msg();
    void slotRecv(char *buf, int len);
    void on_btn_open_clicked();
    void on_btn_clear_clicked();
    void on_btn_send_clicked();
    void on_open_file_3_clicked();
};
#endif // WIDGET_H

tcp_thread.cpp

#include "tcp_thread.h"
#include <QDebug>

Tcp_Thread::Tcp_Thread(QHostAddress ip,QString port,QObject *parent) : QThread(parent)
{
    start_flag = true; //线程工作标志位
    connect_flag = false; //TCP连接标志位
    recv_flag = false;
    server = new QTcpServer(); //新建一个对象
    server->listen(ip, port.toInt()); //监听端口,等待客户端连接
      qDebug()<<"步骤A";
    connect(server,&QTcpServer::newConnection,this,&Tcp_Thread::new_client_connect);
     qDebug()<<"步骤E";
//    c=connect(server,&QTcpServer::newConnection,this,&Tcp_Thread::new_client_connect);
//    qDebug()<<c<<endl;
}


void Tcp_Thread::run()
{
    QByteArray data_temp;

    while(start_flag)
    {
        mutex.lock();
        if(!bytes_queue.isEmpty())
        {
            data_temp = bytes_queue.dequeue();
                  qDebug()<<"步骤B";
            msg_queue.enqueue(QString(data_temp));
            emit signal_msg();
        }
        mutex.unlock();
    }
}

void Tcp_Thread::new_client_connect()
{
    socket = server->nextPendingConnection(); //获取客户端套接字
    client_ip = socket->peerAddress();
    client_port = socket->peerPort(); //此时为空
    connect(socket,SIGNAL(readyRead()),this,SLOT(read_tcp()));
    connect(socket, SIGNAL(disconnected()),this, SLOT(socket_disconnect()));
  qDebug()<<"步骤C";
    connect_flag = true;
    msg_queue.enqueue(QString("上线 [%1]").arg(client_ip.toString()));
    emit signal_msg();
//    socket_disconnect();
}

//读取客户端发送来的数据
void Tcp_Thread::read_tcp()
{
    QByteArray buffer;
    buffer = socket->readAll();
     qDebug()<<"步骤D";
    if(recv_flag)
    {
        bytes_queue.enqueue(buffer);
         qDebug()<<buffer;

    }
}

void Tcp_Thread::socket_disconnect()
{
    connect_flag = false;
    msg_queue.enqueue(QString("已断开!"));
    emit signal_msg();
}

void Tcp_Thread::stop()
{
    mutex.lock();
}

void Tcp_Thread::go_on()
{
    mutex.unlock();
}

Tcp_Thread::~Tcp_Thread()
{

}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDir>
#include <QNetworkInterface>
#include <QFileDialog>
#include <QThread>
#include<QDebug>
#include<QImage>
#include<QMessageBox>
#include <windows.h>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->percent->setValue(0);

    //作为服务端,获取本机ip地址,将TCP端口设为9999
    QHostAddress local_ip = get_local_host_ip();
    QString tcp_port = "9999";
  // QString udp_port = "9999";

 //   ui->lineEdit_path->setText(QDir::currentPath()+"/"); //添加项目文件路径到控件

    ui->ip_local->setText(local_ip.toString());

    ui->port_tcp->setText(tcp_port);
    is_ui_visiable(false);

    //新建TCP对象和thread对象
    tcp_thread = new Tcp_Thread(local_ip,tcp_port);
    connect(tcp_thread,&Tcp_Thread::signal_msg,this,&Widget::print_tcp_msg);

    //新建udp对象和thread对象

    //udp_thread = new Udp_Thread(local_ip,udp_port);
   // connect(udp_thread, &Udp_Thread::signal_img, this, &Widget::display_udp_frame); //接收线程信号

    connect(this, &Widget::destroyed, this, &Widget::close_thread); //线程跟随窗口退出

    tcp_thread->start();
   // udp_thread->start();
    tcp_thread->stop();
   //udp_thread->stop(); //暂停udp线程,等到开启接收画面后再开启工作
    ui->record->setText("等待客户端连接...");
}




//显示TCP数据
void Widget::print_tcp_msg()
{
    if(!tcp_thread->msg_queue.isEmpty())
    {
        ui->record->setTextColor(QColor::fromRgb(255,0,0));
        ui->record->append("client:"+tcp_thread->msg_queue.dequeue());
        ui->record->setTextColor(QColor::fromRgb(0,0,0));
        if(!tcp_thread->connect_flag)
        {
            on_btn_open_clicked();
            ui->record->setText("等待客户端连接...");
        }
    }
}

//关闭线程
void Widget::close_thread()
{
    tcp_thread->go_on();
    tcp_thread->start_flag = false; //停止线程
    tcp_thread->quit();
    tcp_thread->wait(); //等待线程处理完手头工作
    if(tcp_thread->connect_flag)
    {
        tcp_thread->socket->abort();
        tcp_thread->server->close();
    }



}


//开启监听
void Widget::on_btn_open_clicked()
{
    if(ui->btn_open->text().toUtf8() == "监听")
    {
        if(tcp_thread->connect_flag)
        {
            ui->btn_open->setText("关闭");
            is_ui_visiable(true); //控件使能

            tcp_thread->go_on(); //继续tcp线程

            tcp_thread->recv_flag = true;
        }
        else
        {
            ui->record->append("无客户端连接!");
        }
    }
    else if(ui->btn_open->text().toUtf8() == "关闭")
    {
        ui->btn_open->setText("监听");

        tcp_thread->recv_flag = false;
        is_ui_visiable(false); //控件失能

        tcp_thread->stop(); //暂停udp线程
        ui->record->clear();
    }
}

void Widget::on_btn_send_clicked()
{
    QString msg = ui->textEdit_send->toPlainText();
    tcp_thread->socket->write(msg.toUtf8());
    tcp_thread->socket->flush();
    ui->record->setTextColor(QColor::fromRgb(0,0,255));
    ui->record->append("server: "+msg);
    ui->record->setTextColor(QColor::fromRgb(0,0,0));
}


//清空接受区
void Widget::on_btn_clear_clicked()
{
    ui->record->clear();
    ui->textEdit_send->clear();
}

//控件是否可操作
void Widget::is_ui_visiable(bool state)
{
//    ui->btn_snap->setEnabled(state);
//    ui->btn_screen_cap->setEnabled(state);
//    ui->lineEdit_path->setEnabled(state);
//    ui->btn_path_change->setEnabled(state);
//    ui->btn_jpg->setEnabled(state);
//    ui->btn_png->setEnabled(state);
    ui->btn_clear->setEnabled(state);
    ui->btn_send->setEnabled(state);
    ui->textEdit_send->setEnabled(state);
}



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

void Widget::on_open_file_3_clicked()
{
    QString filename;
    filename=QFileDialog::getOpenFileName(this,tr("选择图像"),"",tr("Images (*.png *.bmp *.jpg *.tif *.GIF )"));
    if(filename.isEmpty())
    {

         return;

    }
    else
    {
        QImage* img=new QImage;
        if(!( img->load(filename) ) ) //加载图像
        {
            QMessageBox::information(this,tr("打开图像失败"),tr("打开图像失败!"));
            delete img;
            return;
        }
       ui->origin_pic->setPixmap(QPixmap::fromImage(*img));
        ui->origin_pic->setStyleSheet("background: white;");  // 标签白色背景
        ui->origin_pic->setAlignment(Qt::AlignCenter);  // 图片居中
    }
}
//获取本机在局域网下的ip地址
QHostAddress Widget::get_local_host_ip()
{
  QList<QHostAddress> AddressList = QNetworkInterface::allAddresses();

  QHostAddress result;
  foreach(QHostAddress address, AddressList)
  {
      if(address.protocol() == QAbstractSocket::IPv4Protocol &&
         address != QHostAddress::Null &&
         address != QHostAddress::LocalHost)
      {
          if (address.toString().contains("127.0.")){
            continue;
          }

          if(address.toString().contains("192.168.31.")){
            result = address;
            break;
          }
      }
  }

  return result;
}

 

标签:Widget,QT,thread,void,通信,tcp,ui,TCP,include
来源: https://blog.csdn.net/qq_27373819/article/details/123308277

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有