QT--TCP网络通讯工具编写记录

QT–TCP网络通讯工具编写记录



前言

功能描述:
1、实现服务端创建;
2、实现客户端创建 ;
3、实现服务端与客户端的通讯连接,包括:连接响应,断连响应等;
4、实现服务端一对多客户端,单发送消息,多发消息,循环发消息;
5、实现一键获取本地IP4地址;


演示如下:

在这里插入图片描述


一、服务端项目文件:

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。


【1.1】server_tcp.h 服务端声明文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDateTime>
#include <QListWidgetItem>
#include <thread_1.h>
#include <QtNetwork/QNetworkInterface>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;

    //server用于监听端口,获取新的tcp连接的描述符
    QTcpServer *tcpServer;

    QTcpSocket *socket;//TCP通讯的Socket

    QList<QTcpSocket*> listClient; //创建一个容器

    QString currentDateTimeString;//声明一个字符串变量

    QByteArray buffer;

    int socket_ret =0;

    int all_select_ret = 0;


private:
    void startServer(QString &,int port);
    MyThread *thread = new MyThread;


private slots:
    void initNetwork();
    void onNewConnection();
    void disconnectinfo();
    void onSocketReadyRead();
    void getcurrenttime();
    void delataitem();
    void all_slect();
    void send_write(QString &);
    void start_send();


private slots:
    void on_pushButton_clicked();
    void on_pushButton_3_clicked();
    void on_pushButton_4_clicked();
    void on_pushButton_2_clicked();
    void on_listWidget_customContextMenuRequested(const QPoint &pos);
    void on_pushButton_clear1_clicked();
    void on_pushButton_fa2_clicked();
    void on_pushButton_fa1_clicked();
    void on_pushButton_stop_clicked();
    void on_pushButton_getip_clicked();
    void on_pushButton_ontop_clicked();

};


#endif // MAINWINDOW_H


【1.2】thread_1.h 线程处理声明文件

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include "QDebug"

class MyThread : public QThread
{
    Q_OBJECT

public:
    explicit MyThread(QObject *parent = 0);
    void stop();
    void sleeptimeset(int);


protected:
    void run();

private:
    volatile bool stopped;

signals:
    void sendinfo(int);

};

#endif // MYTHREAD_H


【1.3】main.cpp 执行源文件

#include "server_tcp.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}


【1.4】server_tcp.cpp 服务端逻辑实现源文件

#include "server_tcp.h"
#include "ui_server_tcp.h"
#include "QDebug"
#include <QHostAddress>
#include <QThread>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("服务端");
    //窗口打开位置设置
    this->move(568,250);
    this->setWindowIcon(QIcon(":/server.ico"));
    initNetwork();
    ui->pushButton_2->setDisabled(true);
    ui->pushButton_fa1->setDisabled(true); //禁用发送按钮
    ui->pushButton_fa2->setDisabled(true);
    ui->pushButton_stop->setDisabled(true);
    //设置所选项的背景颜色为深绿色
    ui->listWidget->setStyleSheet("QListWidget::item:selected{background-color: #009900}");
    //连接线程函数
    //连接信号和槽函数
    connect(thread,SIGNAL(sendinfo(int)), this, SLOT(start_send()));

}

//初始化网络
void MainWindow::initNetwork()
{
    tcpServer=new QTcpServer(this);

    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));   //绑定槽函数,当有新的连接请求就会调用该函数

}

//连接按钮点击
void MainWindow::on_pushButton_clicked()
{
    //获取地址和端口
    QString addres = ui->lineEdit->text();
    QString port = ui->comboBox->currentText();
    int port_ = port.toInt();
    //服务端监听地址
    startServer(addres,port_);

}

//服务端启动
void MainWindow::startServer(QString &addres,int port)
{

    qDebug() << "=============";
    QString ret = ui->pushButton->text();

    if (ret == "监听")
    {
        if (!tcpServer->listen(QHostAddress(addres), port))
        {
            qDebug() << "Server could not start!";
            ui->textBrowser->append(QString("<font color=\"#FF0000\">Server could not start!</font> "));

        } else {
            qDebug() << "Server started!";
            ui->pushButton->setStyleSheet("background-color: green");
            ui->pushButton->setText("断连");
        }
    } else if(ret == "断连")
    {

        if(socket_ret == 1)
        {
            for (int h = listClient.count(); h <= listClient.count(); h--)
            {
               if (h==0)
               {
                   break;
               }

               int s= listClient.count();

               qDebug() << "断连控制:" << s << h;

               listClient.at(h-1)->disconnectFromHost();

            }
        }
        tcpServer->close();
        qDebug() << "Server close!";
        ui->pushButton->setStyleSheet("background-color: ");
        ui->pushButton->setText("监听");

    }
}


//客户端连接
void MainWindow::onNewConnection()

{
    ui->pushButton_2->setDisabled(false);
    ui->pushButton_fa1->setDisabled(false);
    ui->pushButton_fa2->setDisabled(false);

    qDebug() << "客户端连接...";
    socket_ret = 1;

    socket = tcpServer->nextPendingConnection(); //创建sockit
    listClient.append(socket);                   //将生成的socket添加到容器里

    connect(socket, SIGNAL(disconnected()), this,SLOT(disconnectinfo()));   //绑定槽函数,当客户端连接断掉后,触发disconnected信号,请求就会调用该函数
    connect(socket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));     //绑定槽函数,当接收到客户端的信息后,触发readyRead信号,请求就会调用该函数

    //发送信息至客户端
     socket->write("Hello from TCP Server!");
    //获取对方的IP和端口
    QString ip = socket->peerAddress().toString();
    int port = socket->peerPort(); //该函数返回一个16位整数,表示连接到的远程主机的端口号

    QString temp = QString("%1:%2").arg(ip).arg(port);

    getcurrenttime();//获取当期时间
    ui->textBrowser->append(QString("<font color=\"#0000FF\">%1: </font> "
                                    "<font color=\"#3D9140\">%2====成功连接</font>").arg(currentDateTimeString,temp));

    //添加连接至listwidget
    ui->listWidget->addItem(temp);

}


//客户端断连后,调用该函数
void MainWindow::disconnectinfo()
{
    qDebug() << listClient.count();

    //监听是那个客户端断连
    QTcpSocket* clientSocket = qobject_cast<QTcpSocket*>(sender());

    int port =0;
    QString address;
    //利用for循环循环列表中的每一个连接进来的客户端,判断是哪一个客户端发的数据
    for (int i = 0; i < listClient.count(); i++)
    {
        socket = listClient.at(i);
        if (socket == clientSocket) {
               // 找到该客户端,进行处理
               address = socket->peerAddress().toString();;
               port = socket->peerPort();
               qDebug() << "Client " << address << ":" << port << " disconnected.";
               break; //结束循环
               }
    }

    QString temp = QString("%1:%2").arg(address).arg(port);
    //    qDebug() << temp;

    getcurrenttime();//获取当期时间
    ui->textBrowser->append(QString("<font color=\"#0000FF\">%1:</font> "
                                    "<font color=\"#FF0000\">%2:客户端断连成功!</font>").arg(currentDateTimeString,temp));

    qDebug() << "客户端断连!";
    for(int i=0; i<ui->listWidget->count(); i++)
        {
        QListWidgetItem *item = ui->listWidget->item(i); // 获取第i行的项
        QString text = item->text(); // 获取第i行的文本
            // 处理获取到的数据
            if (text == temp)
                {
                    delete ui->listWidget->takeItem(i);
                    //删除对应的客户端IP
                    listClient.removeAt(i);
                    //与客户端断连
                    socket->close();
                    if (all_select_ret == 0)
                    {
                        //不选择所有项,设置QT ListWidget中的所有项都未选中
                        ui->listWidget->setCurrentItem(nullptr);
                    }

                }
        }
    //判断是否还有客户端连接服务端
    int connect_count = listClient.count();
    if (connect_count == 0)
    {
        ui->pushButton_fa1->setDisabled(true); //禁用发送按钮
        ui->pushButton_fa2->setDisabled(true);
        ui->pushButton_2->setDisabled(true);
    }
}


//读取数据
void MainWindow::onSocketReadyRead()
{
    qDebug() << "读取数据:";
    //监听是那个客户端断连
    QTcpSocket* clientSocket = qobject_cast<QTcpSocket*>(sender());

    //利用for循环循环列表中的每一个连接进来的客户端,判断是哪一个客户端发的数据
    for (int i = 0; i < listClient.count(); i++)
    {
        socket = listClient.at(i);
        if (socket == clientSocket)
        {
            // 获取端口
            int ports = socket->peerPort();

           // 找到该客户端,进行处理
            QByteArray msg = socket->readAll();
            QString str = QString::fromUtf8(msg);  // 使用UTF-8编码

            getcurrenttime();//获取当期时间

            ui->textBrowser->append(QString("<font color=\"#0000FF\">%1 </font> "
                                            "服务端《======客户端%2: %3").arg(currentDateTimeString).arg(ports).arg(str));
           break; //结束循环
         }
    }

}


//发送按钮
void MainWindow::on_pushButton_2_clicked()
{
    QString info1;
    try {

    //获取发送数据
    QString shuju = ui->textEdit->toPlainText();

    //判断数据长度是否大于0
    if (shuju.length() > 0)
        {
            //获取当前选中行
            int selectedRow = ui->listWidget->currentRow();
            if(selectedRow == -1){
                //没有选中任何项
                getcurrenttime();//获取当期时间
                ui->textBrowser->append(QString("<font color=\"#0000FF\">%1:</font> "
                                                "<font color=\"#FF0000\">没有选中任何客户端</font>").arg(currentDateTimeString));
                return;
            }else
            {
                //获取选中多少行
                QList<QListWidgetItem*> selectedItems = ui->listWidget->selectedItems();
                foreach(QListWidgetItem* item, selectedItems)
                {
                    // 获取当前项目
                    QString info1 = item->text();
                    //qDebug() << "获取选中项:" << info1;
                     //判断当前项目的文本
                     if (info1 != "")
                     {
                          //利用for循环循环列表中的每一个连接进来的客户端,判断是哪一个客户端发的数据
                          for (int i = 0; i < listClient.count(); i++)
                          {
                              socket = listClient.at(i);

                             // 找到该客户端,进行处理
                             QString address = socket->peerAddress().toString();;
                             int port = socket->peerPort();
                             QString ports = QString::number(port);

                             QString temp = QString("%1:%2").arg(address).arg(port);

                             if (temp == info1)
                             {
                                 //判断连接状态是否正常
                                 if (socket->state()== QAbstractSocket::ConnectedState)
                                 {
                                     //给对方发送数据, 使用套接字是tcpSocket 服务端到客户端
                                     socket->write(shuju.toUtf8().data());//
                                     getcurrenttime();//获取当期时间
                                     ui->textBrowser->append(QString("<font color=\"#0000FF\">%1 服务端=====>>>客户端【%2】: </font> %3").arg(currentDateTimeString,ports,shuju));
                                 }
                             }
                           }
                     } else
                     {
                         ui->textBrowser->append(QString("<font color=\"#FF0000\">未选择客户端!</font> "));
                         return;
                     }

                }

            }




        } else
            {
                ui->textBrowser->append(QString("<font color=\"#FF0000\">未填写发送数据!</font> "));
            }

}
    catch(std::exception& e)
    {
        // 捕获并处理异常
        qDebug() << "Exception caught: " << e.what();
    }

}


//发送数据的函数
void MainWindow::send_write(QString &shuju)
{
    QString shujus;
    //判断数据长度是否大于0
    if (shuju.length() > 0)
        {
            int selectedRow = ui->listWidget->currentRow();
            if(selectedRow == -1){
                //没有选中任何项
                getcurrenttime();//获取当期时间
                ui->textBrowser->append(QString("<font color=\"#0000FF\">%1:</font> "
                                                "<font color=\"#FF0000\">没有选中任何客户端</font>").arg(currentDateTimeString));
                return;
            } else
            {
                //获取选中多少行
                QList<QListWidgetItem*> selectedItems = ui->listWidget->selectedItems();
                foreach(QListWidgetItem* item, selectedItems) {
                    //获取当前项目
                    QString shujus = item->text();
                    //qDebug() << "获取选中项:" << shujus;
                    //判断当前项目的文本
                    if (shujus.length() > 0)
                    {
                         //qDebug() << shujus;
                         //利用for循环循环列表中的每一个连接进来的客户端,判断是哪一个客户端发的数据
                         for (int i = 0; i < listClient.count(); i++)
                         {
                             socket = listClient.at(i);

                            // 找到该客户端,进行处理
                            QString address = socket->peerAddress().toString();;
                            int port = socket->peerPort();
                            QString ports = QString::number(port);

                            QString temp = QString("%1:%2").arg(address).arg(port);

                            if (temp == shujus)
                            {
                                //判断连接状态是否正常
                                if (socket->state()== QAbstractSocket::ConnectedState)
                                {
                                    //给对方发送数据, 使用套接字是tcpSocket 服务端到客户端
                                    socket->write(shuju.toUtf8().data());//
                                    getcurrenttime();//获取当期时间
                                    ui->textBrowser->append(QString("<font color=\"#0000FF\">%1 服务端=====>>>客户端【%2】: </font> %3").arg(currentDateTimeString,ports,shuju));
                                }
                            }
                          }
                    } else
                    {
                        ui->textBrowser->append(QString("<font color=\"#FF0000\">未选择客户端!</font> "));
                        return;
                    }

                }

            }

        } else
            {
                ui->textBrowser->append(QString("<font color=\"#FF0000\">未填写发送数据!</font> "));
            }

}




//获取当前时间模块
void MainWindow::getcurrenttime()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    currentDateTimeString = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");
//    qDebug() << "当前时间:" << currentDateTimeString;
}



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


//清空按钮1
void MainWindow::on_pushButton_4_clicked()
{
    ui->textEdit->clear();
}

//清空按钮2
void MainWindow::on_pushButton_3_clicked()
{
    ui->textBrowser->clear();
}

//listWidget中创建右键菜单
void MainWindow::on_listWidget_customContextMenuRequested(const QPoint &pos)
{
       QListWidgetItem* curItem = ui->listWidget->itemAt( pos );
       if( curItem == NULL )
           return;

       QMenu *popMenu = new QMenu( this );
       QAction *Menu1 = new QAction(tr("删除"), this);
       QAction *Menu2 = new QAction(tr("全选"), this);

       popMenu->addAction( Menu1 );
       popMenu->addAction( Menu2 );

       connect( Menu1, SIGNAL(triggered() ), this, SLOT( delataitem()));
       connect( Menu2, SIGNAL(triggered() ), this, SLOT( all_slect()));

       popMenu->exec( QCursor::pos() );
}

//删除选择客户端
void MainWindow::delataitem()
{
    //获取当前项目
    QString ip_port = ui->listWidget->currentItem()->text();
    qDebug() << ip_port;
    //移除当前客户端连接
    //利用for循环循环列表中的每一个连接进来的客户端,判断是哪一个客户端发的数据
    for (int i = 0; i < listClient.count(); i++)
    {
        socket = listClient.at(i);

       // 找到该客户端,进行处理
       QString address = socket->peerAddress().toString();;
       int port = socket->peerPort();

       QString temp = QString("%1:%2").arg(address).arg(port);
       if (temp == ip_port)
       {
            qDebug() << "Client " << address << ":" << port << " disconnected.";

            //删除对应的客户端IP
            listClient.removeAt(i);
            socket->close();
            delete ui->listWidget->takeItem(i);
            break; //结束循环
        }
    }
}

//右键菜单选择所有项目
void MainWindow::all_slect()
{
    //选择所有项目
    qDebug() << "选择所有项目";
    //设置为多选模式
    ui->listWidget->setSelectionMode(QAbstractItemView::MultiSelection);
    ui->listWidget->selectAll();
    all_select_ret = 1;
}


//清空按钮
void MainWindow::on_pushButton_clear1_clicked()
{
    ui->lineEdit_fasong1->clear();
}

//循环发送信息按钮
void MainWindow::on_pushButton_fa2_clicked()
{
    thread->start();
    //启用禁止按钮
    ui->pushButton_stop->setDisabled(false);
    ui->pushButton_fa2->setDisabled(true);
}



//循环函数
void MainWindow::start_send()
{
    qDebug() << "执行...";
    QString shujus;
    //获取数据
    QString shuju = ui->lineEdit_fasong2->text();
    if (shuju.length() > 0)
    {
        int selectedRow = ui->listWidget->currentRow();
        if(selectedRow == -1){
            //没有选中任何项
            getcurrenttime();//获取当期时间
            ui->textBrowser->append(QString("<font color=\"#0000FF\">%1:</font> "
                                            "<font color=\"#FF0000\">未连接任何客户端</font>").arg(currentDateTimeString));
            on_pushButton_stop_clicked();
            return;
        }else
        {

            //获取选中多少行
            QList<QListWidgetItem*> selectedItems = ui->listWidget->selectedItems();

            foreach(QListWidgetItem* item, selectedItems)
            {
                // 获取当前项目
                QString shujus = item->text();
//                qDebug() << "获取选中多少行" << shujus;
                //服务端发送数据到客户端
                //获取当前项目
                if (shujus.length() > 0)
                {
                     //利用for循环循环列表中的每一个连接进来的客户端,判断是哪一个客户端发的数据
                     for (int i = 0; i < listClient.count(); i++)
                     {
                         socket = listClient.at(i);

                        // 找到该客户端,进行处理
                        QString address = socket->peerAddress().toString();;
                        int port = socket->peerPort();
                        QString ports = QString::number(port);

                        QString temp = QString("%1:%2").arg(address).arg(port);

                        if (temp == shujus)
                        {
                            //判断连接状态是否正常
                            if (socket->state()== QAbstractSocket::ConnectedState)
                            {

                                //给对方发送数据, 使用套接字是tcpSocket 服务端到客户端
                                socket->write(shuju.toUtf8().data());//
                                getcurrenttime();//获取当期时间
                                ui->textBrowser->append(QString("<font color=\"#0000FF\">%1 服务端=====>>>客户端【%2】: </font> %3").arg(currentDateTimeString,ports,shuju));
                            }
                        }
                      }
                } else
                {
                    ui->textBrowser->append(QString("<font color=\"#FF0000\">未选择客户端!</font> "));
                    on_pushButton_stop_clicked();
                    return;
                }
            }

        }

    } else
        {
            ui->textBrowser->append(QString("<font color=\"#FF0000\">未填写发送数据!</font> "));
            on_pushButton_stop_clicked();
        }

}



//发送按钮2
void MainWindow::on_pushButton_fa1_clicked()
{
    //获取发送数据
    QString shuju = ui->lineEdit_fasong1->text();
    send_write(shuju);

}

//停止循环按钮
void MainWindow::on_pushButton_stop_clicked()
{
    thread->stop();
    ui->pushButton_fa2->setDisabled(false);
    ui->pushButton_stop->setDisabled(true);
}

//获取本机IP4地址
void MainWindow::on_pushButton_getip_clicked()
{
    getcurrenttime();//获取当期时间
    // 获取IP4地址
    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
        if (address.protocol() == QAbstractSocket::IPv4Protocol && !address.isLoopback())
        {
//            qDebug() << "IP Address: " << address.toString();
            ui->textBrowser->append(QString("<font color=\"#0000FF\">%1 IP4 Address : </font> %2").arg(currentDateTimeString,address.toString()));

        }
    }

}

//窗口置顶
void MainWindow::on_pushButton_ontop_clicked()
{
    QString shuju = ui->pushButton_ontop->text();
    if(shuju == "窗口置顶")
    {
        this->setWindowFlags(Qt::WindowStaysOnTopHint);
        ui->pushButton_ontop->setText("取消置顶");
        this->show();
    }else if (shuju == "取消置顶")
    {
        // 获取窗口原有属性
        Qt::WindowFlags flags = windowFlags();

        // 修改窗口属性,去掉置顶属性
        flags &= ~Qt::WindowStaysOnTopHint;

        // 更新窗口属性
        this->setWindowFlags(flags);
        ui->pushButton_ontop->setText("窗口置顶");
        this->show();
    }

}

【1.5】thread_1.cpp 线程逻辑控制实现源文件

#include "thread_1.h"


int timeset = 1000;

MyThread::MyThread(QObject *parent) :
    QThread(parent)
{
    stopped = false;

}

void MyThread::run()
{
    qDebug() << "线程启动成功======";
    stopped = false;
    int shuju = 1;
    while (!stopped) {
        QThread::msleep(timeset);  // 休眠1000毫秒,即1秒;
        emit sendinfo(shuju);
    }
}

void MyThread::stop()
{
    stopped = true;
}


void MyThread::sleeptimeset(int value=200)
{
    timeset = value;
}



【1.6】server_tcp.ui 服务端UI设计文件

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>705</width>
    <height>373</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="1">
     <widget class="QLineEdit" name="lineEdit">
      <property name="minimumSize">
       <size>
        <width>0</width>
        <height>25</height>
       </size>
      </property>
      <property name="maximumSize">
       <size>
        <width>115</width>
        <height>16777215</height>
       </size>
      </property>
      <property name="text">
       <string>192.168.1.200</string>
      </property>
     </widget>
    </item>
    <item row="5" column="3">
     <widget class="QGroupBox" name="groupBox_2">
      <property name="title">
       <string>接收</string>
      </property>
      <layout class="QGridLayout" name="gridLayout_3">
       <item row="2" column="0">
        <spacer name="horizontalSpacer_2">
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
           <width>40</width>
           <height>20</height>
          </size>
         </property>
        </spacer>
       </item>
       <item row="2" column="2">
        <widget class="QPushButton" name="pushButton_3">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>清空</string>
         </property>
        </widget>
       </item>
       <item row="0" column="0" colspan="3">
        <widget class="QTextBrowser" name="textBrowser"/>
       </item>
       <item row="2" column="1">
        <widget class="QPushButton" name="pushButton_ontop">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>窗口置顶</string>
         </property>
         <property name="checkable">
          <bool>false</bool>
         </property>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
    <item row="0" column="0">
     <widget class="QLabel" name="label">
      <property name="minimumSize">
       <size>
        <width>100</width>
        <height>25</height>
       </size>
      </property>
      <property name="maximumSize">
       <size>
        <width>100</width>
        <height>16777215</height>
       </size>
      </property>
      <property name="frameShape">
       <enum>QFrame::WinPanel</enum>
      </property>
      <property name="frameShadow">
       <enum>QFrame::Raised</enum>
      </property>
      <property name="text">
       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;地址:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
     </widget>
    </item>
    <item row="1" column="1">
     <widget class="QComboBox" name="comboBox">
      <property name="minimumSize">
       <size>
        <width>0</width>
        <height>25</height>
       </size>
      </property>
      <item>
       <property name="text">
        <string>1314</string>
       </property>
      </item>
      <item>
       <property name="text">
        <string>2000</string>
       </property>
      </item>
     </widget>
    </item>
    <item row="1" column="0">
     <widget class="QLabel" name="label_2">
      <property name="minimumSize">
       <size>
        <width>0</width>
        <height>25</height>
       </size>
      </property>
      <property name="frameShape">
       <enum>QFrame::WinPanel</enum>
      </property>
      <property name="frameShadow">
       <enum>QFrame::Raised</enum>
      </property>
      <property name="text">
       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;端口:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
     </widget>
    </item>
    <item row="2" column="1">
     <widget class="QPushButton" name="pushButton">
      <property name="minimumSize">
       <size>
        <width>0</width>
        <height>25</height>
       </size>
      </property>
      <property name="text">
       <string>监听</string>
      </property>
     </widget>
    </item>
    <item row="0" column="3" rowspan="4">
     <widget class="QGroupBox" name="groupBox">
      <property name="title">
       <string>发送</string>
      </property>
      <layout class="QGridLayout" name="gridLayout_2">
       <item row="0" column="4">
        <widget class="QPushButton" name="pushButton_4">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>清空</string>
         </property>
        </widget>
       </item>
       <item row="0" column="0" colspan="3">
        <widget class="QTextEdit" name="textEdit">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>16777215</width>
           <height>25</height>
          </size>
         </property>
        </widget>
       </item>
       <item row="0" column="3">
        <widget class="QPushButton" name="pushButton_2">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>发送</string>
         </property>
        </widget>
       </item>
       <item row="1" column="3">
        <widget class="QPushButton" name="pushButton_fa1">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>发送</string>
         </property>
        </widget>
       </item>
       <item row="1" column="0" colspan="3">
        <widget class="QLineEdit" name="lineEdit_fasong1">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>16777215</width>
           <height>16777215</height>
          </size>
         </property>
        </widget>
       </item>
       <item row="1" column="4">
        <widget class="QPushButton" name="pushButton_clear1">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>清空</string>
         </property>
        </widget>
       </item>
       <item row="2" column="3">
        <widget class="QPushButton" name="pushButton_fa2">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>循环发送</string>
         </property>
        </widget>
       </item>
       <item row="2" column="0" colspan="3">
        <widget class="QLineEdit" name="lineEdit_fasong2">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
        </widget>
       </item>
       <item row="2" column="4">
        <widget class="QPushButton" name="pushButton_stop">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>停止</string>
         </property>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
    <item row="3" column="0" rowspan="3" colspan="2">
     <widget class="QGroupBox" name="groupBox_3">
      <property name="title">
       <string>客户端连接</string>
      </property>
      <layout class="QGridLayout" name="gridLayout_4">
       <item row="0" column="0">
        <widget class="QListWidget" name="listWidget">
         <property name="contextMenuPolicy">
          <enum>Qt::CustomContextMenu</enum>
         </property>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
    <item row="2" column="0">
     <widget class="QPushButton" name="pushButton_getip">
      <property name="minimumSize">
       <size>
        <width>0</width>
        <height>25</height>
       </size>
      </property>
      <property name="text">
       <string>获取本地IP</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>705</width>
     <height>23</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>


【1.7】img.qrc 窗口图标文件


二、客户端项目文件:

在这里插入图片描述


【2.1】client_tcp.h 客户端声明文件

#ifndef CLIENT_TCP_H
#define CLIENT_TCP_H

#include <QWidget>
#include <QTcpSocket>
#include <QDateTime>

namespace Ui {
class client_tcp;
}

class client_tcp : public QWidget
{
    Q_OBJECT

public:
    explicit client_tcp(QWidget *parent = nullptr);
    ~client_tcp();

private slots:
    void on_pushButton_clicked();
    void onConnected();
    void onDisconnected();
    void readdate();
    void on_pushButton_2_clicked();
    void getcurrenttime();

    void on_pushButton_5_clicked();
    void on_pushButton_3_clicked();
    void on_pushButton_4_clicked();

    void on_pushButton_6_clicked();

private:
    Ui::client_tcp *ci;
    QTcpSocket *tcpClient;
    QString currentDateTimeString;

};



#endif // CLIENT_TCP_H

【2.2】client_tcp.cpp 客户端逻辑控制源文件

#include "client_tcp.h"
#include "ui_client_tcp.h"
#include <QHostAddress>
#include "QDebug"



client_tcp::client_tcp(QWidget *parent) :
    QWidget(parent),
    ci(new Ui::client_tcp)
{
    ci->setupUi(this);
    this->setWindowTitle("客户端");
    //窗口打开位置设置
    this->move(1268,250);
    //设置图标
    this->setWindowIcon(QIcon(":/client.ico"));
    //先禁用发送按钮
    ci->pushButton_2->setDisabled(true);
    ci->pushButton_3->setDisabled(true);
    ci->pushButton_4->setDisabled(true);
}


client_tcp::~client_tcp()
{
    delete ci;
}

//点击连接按钮
void client_tcp::on_pushButton_clicked()
{
    //获取地址和端口
    QString ip = ci->lineEdit->text();
    QString port = ci->comboBox->currentText();
    int port_ = port.toInt();

    QString ret_  = ci->pushButton->text();
    if (ret_ == "连接")
    {
        tcpClient =new QTcpSocket(this); //tcpClient
        connect(tcpClient,SIGNAL(connected()),this,SLOT(onConnected()));        //当客户端与服务端建立连接关系后,触发该信号
        connect(tcpClient,SIGNAL(disconnected()),this,SLOT(onDisconnected()));  //当客户端与服务端断连后,触发该信号
        connect(tcpClient,SIGNAL(readyRead()),this,SLOT(readdate()));

        //客户端连接服务端
        tcpClient->connectToHost(QHostAddress(ip),port_);

        //判断客户端是否连接成功
        if (tcpClient->waitForConnected(100)) {
            qDebug() << "Connected to server!";
            //设置字体为绿色
            getcurrenttime();//获取时间模块
            ci->textBrowser->append(QString("<font color=\"#0000FF\">%1:</font>"
                                            "<font color=\"#00FF00\">Connected to server Success!</font>").arg(currentDateTimeString));

            ci->pushButton->setText("断开"); //设置按钮文本
            ci->pushButton->setStyleSheet("background-color: green");//设置按钮背景颜色

            //启用发送按钮
            ci->pushButton_2->setDisabled(false);
            ci->pushButton_3->setDisabled(false);
            ci->pushButton_4->setDisabled(false);
            // tcpClient->write("客户端连接成功!"); //发送信息到服务端
        } else {
            // qDebug() << "Could not connect to server!";

            getcurrenttime();//获取时间模块
            //设置字体为红色
            ci->textBrowser->append(QString("<font color=\"#0000FF\">%1</font>"
                                            "<font color=\"#FF0000\">:Could not connect to serve</font> ").arg(currentDateTimeString));

        }
    }else if(ret_ == "断开")
    {
        tcpClient->close();
        ci->pushButton->setText("连接");
        ci->pushButton->setStyleSheet("background-color: ");
        ci->pushButton_2->setDisabled(true);
        ci->pushButton_3->setDisabled(true);
        ci->pushButton_4->setDisabled(true);
    }

}

//连接触发该函数
void client_tcp::onConnected()
{
     qDebug() << "***客户端已连接到服务器***";
}

//断连触发该函数
void client_tcp::onDisconnected()
{
     qDebug() << "***已断连***";
     tcpClient->close();
     ci->pushButton->setText("连接");
     ci->pushButton->setStyleSheet("background-color: ");


}

//读取服务端发送过来的数据
void client_tcp::readdate()
{

    QByteArray msg = tcpClient->readAll();

    QString str(msg);
    getcurrenttime();//获取时间模块

    ci->textBrowser->append(QString("<font color=\"#0000FF\"> %1 </font>"
                                    "客户端《======服务端 %2").arg(currentDateTimeString,msg));

}


//获取当前时间模块
void client_tcp::getcurrenttime()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    currentDateTimeString = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");
//    qDebug() << "当前时间:" << currentDateTimeString;
}


//清空按钮
void client_tcp::on_pushButton_5_clicked()
{
    ci->textBrowser->clear();
}


//发送按钮1
void client_tcp::on_pushButton_2_clicked()
{
    //读取文本框内的数据
    QString shuju1 = ci->lineEdit_2->text();
    if (shuju1.length()> 0)
    {
        //判断连接状态是否正常
        if (tcpClient->state()== QAbstractSocket::ConnectedState)
        {
            //给对方发送数据, 使用套接字是tcpSocket 客户端到服务端
            tcpClient->write(shuju1.toUtf8().data());//
            getcurrenttime();//获取时间模块

            ci->textBrowser->append(QString("<font color=\"#0000FF\">%1 客户端=====>>>服务端: </font>"
                                            "%2").arg(currentDateTimeString,shuju1));
        }
    }
}


//发送按钮2
void client_tcp::on_pushButton_3_clicked()
{
    //读取文本框内的数据
    QString shuju1 = ci->lineEdit_3->text();
    if (shuju1.length()> 0)
    {
        //判断连接状态是否正常
        if (tcpClient->state()== QAbstractSocket::ConnectedState)
        {
            //给对方发送数据, 使用套接字是tcpSocket 客户端到服务端
            tcpClient->write(shuju1.toUtf8().data());//
            getcurrenttime();//获取时间模块

            ci->textBrowser->append(QString("<font color=\"#0000FF\">%1 客户端=====>>>服务端: </font>"
                                            "%2").arg(currentDateTimeString,shuju1));
        }
    }
}


//发送按钮3
void client_tcp::on_pushButton_4_clicked()
{
    //读取文本框内的数据
    QString shuju1 = ci->lineEdit_4->text();
    if (shuju1.length()> 0)
    {
        //判断连接状态是否正常
        if (tcpClient->state()== QAbstractSocket::ConnectedState)
        {
            //给对方发送数据, 使用套接字是tcpSocket 客户端到服务端
            tcpClient->write(shuju1.toUtf8().data());//
            getcurrenttime();//获取时间模块

            ci->textBrowser->append(QString("<font color=\"#0000FF\">%1 客户端=====>>>服务端: </font>"
                                            "%2").arg(currentDateTimeString,shuju1));
        }
    }
}

//窗口置顶
void client_tcp::on_pushButton_6_clicked()
{
    QString shuju = ci->pushButton_6->text();
    if(shuju == "窗口置顶")
    {
        this->setWindowFlags(Qt::WindowStaysOnTopHint);
        ci->pushButton_6->setText("取消置顶");
        this->show();
    }else if (shuju == "取消置顶")
    {
        // 获取窗口原有属性
        Qt::WindowFlags flags = windowFlags();

        // 修改窗口属性,去掉置顶属性
        flags &= ~Qt::WindowStaysOnTopHint;

        // 更新窗口属性
        this->setWindowFlags(flags);
        ci->pushButton_6->setText("窗口置顶");
        this->show();
    }
}


【2.2】main.cpp 执行源文件

#include "client_tcp.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    client_tcp w;
    w.show();
    return a.exec();
}


【2.3】client_tcp.ui 客户端UI设计文件

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>client_tcp</class>
 <widget class="QWidget" name="client_tcp">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>602</width>
    <height>432</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="1">
    <widget class="QLineEdit" name="lineEdit">
     <property name="minimumSize">
      <size>
       <width>0</width>
       <height>28</height>
      </size>
     </property>
     <property name="maximumSize">
      <size>
       <width>300</width>
       <height>16777215</height>
      </size>
     </property>
     <property name="text">
      <string>192.168.1.200</string>
     </property>
    </widget>
   </item>
   <item row="1" column="0" colspan="2">
    <widget class="QGroupBox" name="groupBox">
     <property name="maximumSize">
      <size>
       <width>400</width>
       <height>16777215</height>
      </size>
     </property>
     <property name="title">
      <string>发送</string>
     </property>
     <layout class="QGridLayout" name="gridLayout_2">
      <item row="1" column="1">
       <widget class="QPushButton" name="pushButton_3">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>28</height>
         </size>
        </property>
        <property name="text">
         <string>发送2</string>
        </property>
       </widget>
      </item>
      <item row="2" column="1">
       <widget class="QPushButton" name="pushButton_4">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>28</height>
         </size>
        </property>
        <property name="text">
         <string>发送3</string>
        </property>
       </widget>
      </item>
      <item row="2" column="0">
       <widget class="QLineEdit" name="lineEdit_4">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>28</height>
         </size>
        </property>
       </widget>
      </item>
      <item row="0" column="1">
       <widget class="QPushButton" name="pushButton_2">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>28</height>
         </size>
        </property>
        <property name="text">
         <string>发送1</string>
        </property>
       </widget>
      </item>
      <item row="0" column="0">
       <widget class="QLineEdit" name="lineEdit_2">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>28</height>
         </size>
        </property>
       </widget>
      </item>
      <item row="1" column="0">
       <widget class="QLineEdit" name="lineEdit_3">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>28</height>
         </size>
        </property>
       </widget>
      </item>
      <item row="3" column="0">
       <spacer name="verticalSpacer">
        <property name="orientation">
         <enum>Qt::Vertical</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>20</width>
          <height>40</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </widget>
   </item>
   <item row="0" column="2">
    <widget class="QLabel" name="label_2">
     <property name="minimumSize">
      <size>
       <width>0</width>
       <height>28</height>
      </size>
     </property>
     <property name="maximumSize">
      <size>
       <width>60</width>
       <height>16777215</height>
      </size>
     </property>
     <property name="frameShape">
      <enum>QFrame::WinPanel</enum>
     </property>
     <property name="frameShadow">
      <enum>QFrame::Raised</enum>
     </property>
     <property name="text">
      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;端口:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
     </property>
    </widget>
   </item>
   <item row="1" column="2" colspan="3">
    <widget class="QGroupBox" name="groupBox_2">
     <property name="title">
      <string>接收</string>
     </property>
     <layout class="QGridLayout" name="gridLayout_3">
      <item row="1" column="0">
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
      <item row="1" column="2">
       <widget class="QPushButton" name="pushButton_5">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>28</height>
         </size>
        </property>
        <property name="text">
         <string>清空</string>
        </property>
       </widget>
      </item>
      <item row="0" column="0" colspan="3">
       <widget class="QTextBrowser" name="textBrowser"/>
      </item>
      <item row="1" column="1">
       <widget class="QPushButton" name="pushButton_6">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>25</height>
         </size>
        </property>
        <property name="text">
         <string>窗口置顶</string>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
   <item row="0" column="4">
    <widget class="QPushButton" name="pushButton">
     <property name="minimumSize">
      <size>
       <width>0</width>
       <height>28</height>
      </size>
     </property>
     <property name="text">
      <string>连接</string>
     </property>
    </widget>
   </item>
   <item row="0" column="0">
    <widget class="QLabel" name="label">
     <property name="minimumSize">
      <size>
       <width>0</width>
       <height>28</height>
      </size>
     </property>
     <property name="maximumSize">
      <size>
       <width>100</width>
       <height>16777215</height>
      </size>
     </property>
     <property name="frameShape">
      <enum>QFrame::WinPanel</enum>
     </property>
     <property name="frameShadow">
      <enum>QFrame::Raised</enum>
     </property>
     <property name="text">
      <string>地址:</string>
     </property>
    </widget>
   </item>
   <item row="0" column="3">
    <widget class="QComboBox" name="comboBox">
     <property name="minimumSize">
      <size>
       <width>0</width>
       <height>28</height>
      </size>
     </property>
     <item>
      <property name="text">
       <string>1314</string>
      </property>
     </item>
     <item>
      <property name="text">
       <string>2000</string>
      </property>
     </item>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

三、设置项目构建的位置:

在这里插入图片描述
在这里插入图片描述

四、QT项目不能用于其他电脑的原因:

删除该用户记录文件,其他电脑上的QT都可打开同一个项目;
在这里插入图片描述

五、编译程序,使exe执行文件可正常使用:

【5.1】 打开该文件

在这里插入图片描述

【5.2】 进入项目构建的文件目录内,输入指令:windeployqt.exe connect_tcp.exe【这是你自己已构建的exe执行程序】

如下图所示:直接运行exe程序,会报错,缺少需要的文件。
在这里插入图片描述

输入指令后,会自动生成exe执行所需要的文件
在这里插入图片描述

再次点击exe执行文件,软件正常打开使用

在这里插入图片描述

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山中坐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值