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

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


文章目录

  • QT--TCP网络通讯工具编写记录
  • 前言
  • 演示如下:
  • 一、服务端项目文件:
    • 【1.1】server_tcp.h 服务端声明文件
    • 【1.2】thread_1.h 线程处理声明文件
    • 【1.3】main.cpp 执行源文件
    • 【1.4】server_tcp.cpp 服务端逻辑实现源文件
    • 【1.5】thread_1.cpp 线程逻辑控制实现源文件
    • 【1.6】server_tcp.ui 服务端UI设计文件
    • 【1.7】img.qrc 窗口图标文件
  • 二、客户端项目文件:
    • 【2.1】client_tcp.h 客户端声明文件
    • 【2.2】client_tcp.cpp 客户端逻辑控制源文件
    • 【2.2】main.cpp 执行源文件
    • 【2.3】client_tcp.ui 客户端UI设计文件
  • 三、设置项目构建的位置:
  • 四、QT项目不能用于其他电脑的原因:
  • 五、编译程序,使exe执行文件可正常使用:
    • 【5.1】 打开该文件
    • 【5.2】 进入项目构建的文件目录内,输入指令:windeployqt.exe **connect_tcp.exe【这是你自己已构建的exe执行程序】**


前言

功能描述:
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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;//server用于监听端口,获取新的tcp连接的描述符QTcpServer *tcpServer;QTcpSocket *socket;//TCP通讯的SocketQList<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_OBJECTpublic: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(); //创建sockitlistClient.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));//添加连接至listwidgetui->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);//删除对应的客户端IPlistClient.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();//判断数据长度是否大于0if (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;//判断数据长度是否大于0if (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.";//删除对应的客户端IPlistClient.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_OBJECTpublic: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); //tcpClientconnect(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执行文件,软件正常打开使用

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/13623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【最全的excel转json!!!】使用Python脚本提取excel文本中的数据到json中

比如说&#xff1a;我有一个1.xlsx的文件需要转成对应的json格式。 1&#xff09; excel 文件的大概内容&#xff1a; 2&#xff09;保存的方式类似于以下这种情况&#xff1a; 用Python脚本来实现 import pandas as pd import json# 读取Excel文件 excel_path r"D:…

【MySQL精通之路】MySQL8.0升级过程升级了什么

目录 1.升级内容 1.1 mysql系统库 1.2.其他库 2.步骤 2.1 步骤1&#xff1a;数据字典库升级。 2.2 步骤2&#xff1a;服务器升级。 3.mysql_upgrade 3.1 执行正常升级&#xff08;根据需要执行步骤1和2&#xff09;&#xff1a; 3.2 必要时仅执行步骤1&#xff1a; 3…

LLMPerf-为LLM提供可重现的性能指标

LLMPerf-为LLM推理提供可复现的性能指标 翻译自文章&#xff1a;Reproducible Performance Metrics for LLM inference 结合之前的LLMPerf测试大模型API性能的文章进行查看&#xff0c;效果更佳。 1. 摘要 我们见过许多关于LLM性能的声明&#xff1b;然而&#xff0c;这些声明往…

Android面试题之Kotlin泛型和reified关键字

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 //泛型 class MagicBox<T>(item:T){var available falseprivate var subject:T itemfun fetch() : T? {return subject.takeIf { avai…

配置旁挂二层组网直接转发示例(命令行)

业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响用户的业务使用。 组网需求 AC组网方式&#xff1a;旁挂二层组网。DHCP部署方式&#xff1a; AC作为DHCP服务器为AP分配IP地址。汇聚交换机SwitchB作…

深度学习基础之《TensorFlow框架(18)—卷积神经网络(2)》

一、卷积层 1、卷积层&#xff08;Convolutional Layer&#xff09;介绍 卷积神经网络中每层卷积层由若干卷积单元&#xff08;卷积核&#xff09;组成&#xff0c;每个卷积单元的参数都是通过反向传播算法最佳化得到的 卷积运算的目的是特征提取&#xff0c;第一层卷积层可能…

Gradle和Maven项目解决Spring Boot Configuration Annotation Processor not configured警告

问题描述 写了一个配置类,加了注解@ConfigurationProperties(prefix = “xxx”) 后一直报警告:Spring Boot Configuration Annotation Processor not configured 意思是 Spring boot 未配置注解处理器 解决过程 出现这个问题后,百度查了解决方式 1.maven项目 maven项目是…

纯软件双机热备

在信息化高速发展的今天&#xff0c;企业对于业务连续性的需求愈发强烈。无论哪个行业&#xff0c;系统的稳定运行都至关重要。为了确保系统的高可用性和业务连续性&#xff0c;纯软件双机热备技术应运而生&#xff0c;成为了企业IT架构中的关键一环。 双机热备软件下载 …

cPanel中如何进行网站质量检测

最近我在维护网站的时候需要查看网站质量如何&#xff0c;我使用的是Hostease的主机安装的WordPress网站&#xff0c;随后在咨询了他们的技术支持后获得了方法。 当您在cPanel中部署了网站后&#xff0c;确保网站的质量和性能是至关重要的。cPanel提供了一个便捷的功能Site Qu…

Postman进阶功能-Mock服务与监控

大家好&#xff0c;前面跟大家分享一些关于 Postman 的进阶功能&#xff0c;当我们深入探索 Postman 的进阶功能时&#xff0c;Mock 服务与监控这两个重要方面便跃然眼前。 首先&#xff0c;Mock 服务为我们提供了一种灵活便捷的方式&#xff0c;让我们在某些实际接口尚未准备好…

18.SpringCloud Gateway

简介 SpringCloud Gateway是spingcloud家族的产品&#xff0c;使用netty实现的高性能服务网关&#xff0c;用于替换netflix公司的zuul网关实现。 参考地址&#xff1a; https://spring.io/projects/spring-cloud 术语 工作原理 Route Predicate Factories GatewayFilte…

新一代分布式链路追踪skywalking编码实战教程(下)

&#x1f680; 作者 &#xff1a;“二当家-小D” &#x1f680; 博主简介&#xff1a;⭐前荔枝FM架构师、阿里资深工程师||曾任职于阿里巴巴担任多个项目负责人&#xff0c;8年开发架构经验&#xff0c;精通java,擅长分布式高并发架构,自动化压力测试&#xff0c;微服务容器化k…

PostgresSQL开启归档模式

文章目录 一、查询数据库归档是否开启1、查看数据目录(找出conf文件位置)2、查看归档是否开启 二、开启归档模式&#xff08;开启后有一定的性能损耗&#xff09;1、创建归档目录2、修改postgresql.conf配置文件3、重启pg 三、验证归档情况1、查看归档是否开启2、检查点 , 刷新…

利用远控工具横向

一.横向移动介绍和方式 1.介绍 内网渗透的横向移动是指攻击者在成功进入内网后&#xff0c;通过利用内部系统的漏洞或者获取的合法访问权限&#xff0c;从一个受感染的系统向其他系统扩散或移动。这种横向移动的目的通常是为了获取更多的敏感信息、提升权限、扩大攻击面或者更…

【蓝桥杯】

题目列表 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<bits/stdc.h> using llunsigned long long; #define int ll const int N2e510; int k0; std::string s; int a,b,c,d; void solve() {char op;std::cin>>op;if(opA){std::string s;for(int i1;i&l…

文心一言指令解析

1、介绍 文心一言是一款灵感启发类的产品&#xff0c;它以简洁而深刻的文字表达来激发读者的思考和感悟。该产品通过每天提供一句精选的短语&#xff0c;让用户在繁忙的生活中停下脚步&#xff0c;思考人生和内心的真实需求。 每一句文心一言都经过精心挑选&#xff0c;它们通…

小程序-滚动触底-页面列表数据无限加载

// index/index.vue <template> <!-- 自定义导航栏 --> <CustomNavbar /> <scroll-view scrolltolower"onScrolltolower" scroll-y class"scroll-view"> <!-- 猜你喜欢 --> <Guess ref"guessRef" /> </s…

恶劣天气下的车辆探测:多方关注 多模态融合方法

摘要 在自动驾驶汽车技术领域&#xff0c;多模式车辆检测网络(MVDNet)代表了一个重大的飞跃&#xff0c;特别是在具有挑战性的天气条件下。本文主要通过集成多头关注层对MVDNet进行增强&#xff0c;旨在改进其性能。MVDNet模型中集成的多头关注层是一个关键的改进&#xff0c;…

民国漫画杂志《时代漫画》第14期.PDF

时代漫画14.PDF: https://url03.ctfile.com/f/1779803-1247458399-6732ac?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络&#xff01;

java+ vue.js+uniapp一款基于云计算技术的企业级生产管理系统,云MES源码 MES系统如何与ERP系统集成?

java vue.jsuniapp一款基于云计算技术的企业级生产管理系统&#xff0c;云MES源码&#xff0c;MES系统如何与ERP系统集成&#xff1f; MES系统&#xff08;制造执行系统&#xff09;与ERP系统&#xff08;企业资源规划系统&#xff09;的集成可以通过多种方式实现&#xff0c;这…