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地址;
演示如下:
一、服务端项目文件:
【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><html><head/><body><p align="center">地址:</p></body></html></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><html><head/><body><p align="center">端口:</p></body></html></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><html><head/><body><p align="center">端口:</p></body></html></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执行文件,软件正常打开使用