【QT开发】网络调试助手项目
网络相关的一些基础概念-面试用学习QTcpServer学习QTcpClient学习TextEdit特定位置输入文字颜色学习网络通信相关知识点复习巩固之前UI控件程序运行如下图所示。
目录
1 TCP网络调试助手
1.1 项目概述
- 网络相关的一些基础概念-面试用
- 学习QTcpServer
- 学习QTcpClient
- 学习TextEdit特定位置输入文字颜色
- 学习网络通信相关知识点
- 复习巩固之前UI控件
程序运行如下图所示

1.2 开发流程

1.3 QTtcp服务器的关键流程
工程建立,需要在.pro加入网络权限

创建一个基于 QTcpServer 的服务端涉及以下关键步骤:
- 创建并初始化 QTcpServer 实例:
实例化 QTcpServer 。调用 listen 方法在特定端口监听传入的连接。
- 处理新连接:
为 newConnection 信号连接一个槽函数。在槽函数中,使用nextPendingConnection 获取 QTcpSocket 以与客户端通信。
- 读取和发送数据:
通过连接 QTcpSocket 的 readyRead 信号来读取来自客户端的数据。
使用 write 方法发送数据回客户端。
- 关闭连接:
在适当的时候关闭 QTcpSocket 。
示例代码如下:
class MyServer : public QObject {
Q_OBJECT
public:
MyServer() {
QTcpServer *server = new QTcpServer(this);
connect(server, &QTcpServer::newConnection, this,
&MyServer::onNewConnection);
server->listen(QHostAddress::Any, 1234);
}
private slots:
void onNewConnection() {
QTcpSocket *clientSocket = server->nextPendingConnection();
connect(clientSocket, &QTcpSocket::readyRead, this,
&MyServer::onReadyRead);
// ...
}
void onReadyRead() {
QTcpSocket *clientSocket = qobject_cast<QTcpSocket *>(sender());
// 读取数据
QByteArray data = clientSocket->readAll();
// 处理数据
// ...
}
};
确保在使用 QTcpServer 和 QTcpSocket 时妥善处理网络错误和异常情况。
1.4 QTtcp客户端的关键流程
工程建立,需要在.pro加入网络权限

创建一个基于 QTcpSocket 的Qt客户端涉及以下步骤:
- 创建 QTcpSocket 实例:
实例化 QTcpSocket 。
- 连接到服务器:
使用 connectToHost 方法连接到服务器的IP地址和端口。
- 发送数据到服务器:
使用 write 方法发送数据。
- 接收来自服务器的数据:
为 readyRead 信号连接一个槽函数来接收数据。
- 关闭连接:
关闭 QTcpSocket 连接。
示例代码如下:
class MyClient : public QObject {
Q_OBJECT
public:
MyClient() {
QTcpSocket *socket = new QTcpSocket(this);
connect(socket, &QTcpSocket::readyRead, this, &MyClient::onReadyRead);
socket->connectToHost("server_address", 1234);
}
private slots:
void onReadyRead() {
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
QByteArray data = socket->readAll();
// 处理接收到的数据
// ...
}
};
这个客户端尝试连接到指定的服务器地址和端口,然后等待和处理来自服务器的数据。记得根据需要管理和处理网络错误和异常情况。
1.5 TCP协议
以下内容自省阅读和消化,主要在面试之前类似八股文问答,实际编程我们不需要关系这么多,QTcpSocket类底下的API已经做好所有的封装。
TCP(传输控制协议)是一种广泛使用的网络通信协议,设计用于在网络中的计算机之间可靠地传输数据。它是互联网协议套件的核心部分,通常与IP(互联网协议)一起使用,合称为TCP/IP。以下是TCP协议的一些基本特点:
- 面向连接:在数据传输之前,TCP 需要在发送方和接收方之间建立一个连接。这包括三次握手过程,确保两端都准备好进行数据传输。
- 可靠传输:TCP 提供可靠的数据传输服务,这意味着它保证数据包准确无误地到达目的地。如果发生数据丢失或错误,TCP 会重新发送数据包。
- 顺序控制:TCP 保证数据包的传输顺序。即使数据包在网络中的传输顺序被打乱,接收方也能按照正确的顺序重组这些数据。
- 流量控制:TCP 使用窗口机制来控制发送方的数据传输速率,以防止网络过载。这有助于防止接收方被发送方发送的数据所淹没。
- 拥塞控制:TCP 还包括拥塞控制机制,用来检测并防止网络拥塞。当网络拥塞发生时,TCP 会减少其数据传输速率。
- 数据分段:大块的数据在发送前会被分割成更小的段,以便于传输。这些段会被独立发送并在接收端重新组装。
- 确认和重传:接收方对成功接收的数据包发送确认(ACK)信号。如果发送方没有收到确认,它会重传丢失的数据包。
- 终止连接:数据传输完成后,TCP 连接需要被正常关闭,这通常涉及到四次挥手过程。
TCP 适用于需要高可靠性的应用,如网页浏览、文件传输、电子邮件等。然而,由于它的这些特性,TCP在处理速度上可能不如其他协议(如UDP)那么快速。
TCP协议中的三次握手和四次挥手是建立和终止连接的重要过程。下面是它们的简要描述:
三次握手(建立连接)
三次握手的主要目的是在两台设备之间建立一个可靠的连接。它包括以下步骤:
- SYN:客户端向服务器发送一个SYN(同步序列编号)报文来开始一个新的连接。此时,客户端进入SYN-SENT状态。
- SYN-ACK:服务器接收到SYN报文后,回复一个SYN-ACK(同步和确认)报文。此时服务器进入SYN-RECEIVED状态。
- ACK:客户端接收到SYN-ACK后,发送一个ACK(确认)报文作为回应,并进入ESTABLISHED(已建立)状态。服务器在收到这个ACK报文后,也进入ESTABLISHED状态。这标志着连接已经建立。

四次挥手(断开连接)
四次挥手的目的是终止已经建立的连接。这个过程包括以下步骤:
- FIN:当通信的一方完成数据发送任务后,它会发送一个FIN(结束)报文来关闭连接。发送完FIN报文后,该方进入FIN-WAIT-1状态。
- ACK:另一方接收到FIN报文后,发送一个ACK报文作为回应,并进入CLOSE-WAIT状态。发送FIN报文的一方在收到ACK后,进入FIN-WAIT-2状态。
- FIN:在等待一段时间并完成所有数据的发送后,CLOSE-WAIT状态的一方也发送一个FIN报文来请求关闭连接。
- ACK:最初发送FIN报文的一方在收到这个FIN报文后,发送一个ACK报文作为最后的确认,并进入TIME-WAIT状态。经过一段时间后,确保对方接收到了最后的ACK报文,该方最终关闭连接。

在这两个过程中,三次握手主要确保双方都准备好进行通信,而四次挥手则确保双方都已经完成通信并同意关闭连接。
1.6 Socket
Socket 不是一个协议,而是一种编程接口(API)或机制,用于在网络中实现通信。Socket 通常在应用层和传输层之间提供一个端点,使得应用程序可以通过网络发送和接收数据。它支持多种协议,主要是TCP 和 UDP。
以下是 Socket 的一些基本特点:
- 类型:有两种主要类型的 Sockets —— TCP Socket(面向连接,可靠)和 UDP Socket(无连接,不可靠)。
- 应用:在各种网络应用中广泛使用,如网页服务器、聊天应用、在线游戏等。编程语言支持:大多数现代编程语言如 Python, Java, C++, 等都提供 Socket 编程的支持。
- 功能:提供了创建网络连接、监听传入的连接、发送和接收数据等功能。QT: 在QT组件中,QTcpSocket用来管理和实现TCP Socket通信QUdpSocket用来管理和实现UDP Socket通信。
总之,Socket 是实现网络通信的基础工具之一,它抽象化了网络层的复杂性,为开发者提供了一种相对简单的方式来建立和管理网络连接。
2 UI设计
服务端界面

客户端界面

3 网络通信核心代码
QTcpServer 是 Qt 网络模块的一部分,用于构建 TCP 服务器。它提供了一种机制来异步监听来自客户端的连接。一旦接受了一个连接,服务器就可以与客户端进行数据交换。
3.1 创建TCP服务端的核心代码
主要步骤如下:
- 创建 QTcpServer 实例:启动服务器并开始监听指定端口。
- 监听连接请求:调用 listen() 方法使服务器监听特定的 IP 地址和端口。
- 接受连接:当客户端尝试连接时, QTcpServer 产生一个信号。你需要实现一个槽(slot)来响应这个信号,并接受连接。
- 处理客户端连接:每个连接的客户端都关联一个 QTcpSocket 对象,用于数据交换。
示例代码
#include <QTcpServer>
#include <QTcpSocket>
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QTcpServer server;
// 监听端口
if (!server.listen(QHostAddress::Any, 12345)) {
qDebug() << "Server could not start";
return -1;
}
qDebug() << "Server started!";
// 当有新连接时,执行相应的操作
QObject::connect(&server, &QTcpServer::newConnection, [&]() {
QTcpSocket *client = server.nextPendingConnection();
QObject::connect(client, &QTcpSocket::readyRead, [client]() {
QByteArray data = client->readAll();
qDebug() << "Received data:" << data;
client->write("Hello, client!");
});
QObject::connect(client, &QTcpSocket::disconnected, client,
&QTcpSocket::deleteLater);
});
return a.exec();
}
代码解释
- 创建 QTcpServer 对象:在主函数中,直接创建了一个 QTcpServer 对象。
- 监听端口:使用 listen() 方法监听所有接口上的 12345 端口。
- 处理新连接:通过连接 newConnection 信号,当有新客户端连接时,会调用相应的槽函数。
- 读取数据:为每个连接的客户端创建 QTcpSocket 对象,并连接 readyRead 信号以接收数据。
- 发送数据:向客户端发送响应消息。
- 客户端断开连接时的处理:使用 disconnected 信号确保客户端在断开连接时被适当地清理。
这个代码示例展示了如何使用 QTcpServer 创建一个基本的 TCP 服务器,而无需通过继承来扩展类。这种方式通常更简单,适用于不需要复杂处理的基本应用场景。
3.2 创建TCP客户端的核心代码
为了使客户端代码更具模块化和响应性,可以使用 Qt 的信号与槽机制。这种方法允许客户端以事件驱动的方式响应网络事件,如连接建立、数据接收等。下面是一个使用信号与槽的 TCP 客户端示例。
示例代码
#include <QTcpSocket>
#include <QCoreApplication>
#include <QDebug>
class TcpClient : public QObject {
Q_OBJECT
public:
TcpClient(const QString &host, quint16 port) {
connect(&socket, &QTcpSocket::connected, this, &TcpClient::onConnected);
connect(&socket, &QTcpSocket::readyRead, this, &TcpClient::onReadyRead);
socket.connectToHost(host, port);
}
private slots:
void onConnected() {
qDebug() << "Connected to server!";
socket.write("Hello, server!");
}
void onReadyRead() {
QByteArray data = socket.readAll();
qDebug() << "Server said:" << data;
socket.disconnectFromHost();
}
private:
QTcpSocket socket;
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
TcpClient client("localhost", 12345);
return a.exec();
}
代码解释
- 创建 TcpClient 类:这个类继承自 QObject ,允许使用信号与槽机制。
- 连接信号和槽:在构造函数中,将 QTcpSocket 的 connected 和 readyRead 信号分别连接到
onConnected 和 onReadyRead 槽。 - 连接到服务器:使用 connectToHost() 方法开始连接过程。
- 处理连接建立:一旦连接建立, onConnected 槽被触发,客户端向服务器发送一条消息。
- 接收数据:当数据可读时, onReadyRead 槽被触发,客户端读取并打印来自服务器的数据。
- 断开连接:在接收数据后,客户端断开与服务器的连接。
这个客户端示例展示了如何使用 Qt 的信号与槽机制来处理 TCP 连接。这种方式使得代码更加清晰,易于维护,并且能更好地处理异步事件。
4 TCP服务端项目开发
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMessageBox>
#include <QNetworkInterface>
#include <QTcpSocket>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//关联窗口和子组件同步变大变小
this->setLayout(ui->verticalLayout);
//实例化一个服务器对象
server = new QTcpServer(this);
//绑定新客户端连接信号与槽
connect(server,SIGNAL(newConnection()),this,SLOT(on_newClient_conect()));
//为MyComoBox连接信号与槽
connect(ui->comboBoxChildren,&MyComboBox::on_ComboBox_clicked,this,&Widget::myComboBox_refresh);
//设置启动时按钮状态
ui->btnLineOut->setEnabled(false);
ui->btnStopListen->setEnabled(false);
ui->btnSend->setEnabled(false);
//自动获取主机IP地址并刷新到控件上
//QList<QHostAddress> QNetworkInterface::allAddresses()
QList<QHostAddress> addresss = QNetworkInterface::allAddresses();
for(QHostAddress tmp : addresss){
if(tmp.protocol() == QAbstractSocket::IPv4Protocol){
ui->comboBoxAddr->addItem(tmp.toString());
}
}
}
Widget::~Widget()
{
delete ui;
}
//新客户端连接槽函数
void Widget::on_newClient_conect()
{
//判断是否有新加入的客户端
if(server->hasPendingConnections()){
//实例化一个Socket对象,生成对话通道
QTcpSocket *connection = server->nextPendingConnection();
qDebug() << "client Addr:" << connection->peerAddress().toString() <<
" port:" << connection->peerPort();
ui->textEditRev->insertPlainText("客户端地址:"+connection->peerAddress().toString()
+ "\n客户端端口号:" + QString::number(connection->peerPort()) + "\n");
//为接收数据绑定信号与槽
connect(connection,SIGNAL(readyRead()),this,SLOT(on_readyRead_handler()));
//为断开连接绑定信号与槽
connect(connection,SIGNAL(disconnected()),this,SLOT(mdisconnected()));
//为断开连接绑定信号与槽
connect(connection,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this,SLOT(mstateChanged(QAbstractSocket::SocketState)));
//往comboBox中增加条目
ui->comboBoxChildren->addItem(QString::number(connection->peerPort()));
ui->comboBoxChildren->setCurrentText(QString::number(connection->peerPort()));
childIndex = ui->comboBoxChildren->currentIndex();
if(!ui->btnSend->isEnabled()){
ui->btnSend->setEnabled(true);
}
}
}
//开始监听按钮槽函数
void Widget::on_btnListen_clicked()
{
//监听客户端
//QHostAddress addr("10.102.13.233");
//自动检测IP地址:QHostAddress::Any
int port = ui->lineEditPort->text().toInt();
if(!server->listen(QHostAddress(ui->comboBoxAddr->currentText()),port)){
qDebug() << "listenError";
QMessageBox msgBox;
msgBox.setWindowTitle("监听失败");
msgBox.setText("端口号被占用\n");
msgBox.exec();
}else{
//设置按下开始监听按钮后其他按钮状态
ui->btnListen->setEnabled(false);
ui->btnLineOut->setEnabled(true);
ui->btnStopListen->setEnabled(true);
}
}
//数据接收槽函数
void Widget::on_readyRead_handler()
{
//通过信号发送者找到发送者对象
QTcpSocket *tmpSock = qobject_cast<QTcpSocket *>(sender());
QByteArray revData = tmpSock->readAll();
ui->textEditRev->moveCursor(QTextCursor::End);
ui->textEditRev->ensureCursorVisible();
ui->textEditRev->insertPlainText("客户端:" + revData + "\n");
}
//连接断开槽函数
void Widget::mdisconnected()
{
//通过信号发送者找到发送者对象
QTcpSocket *tmpSock = qobject_cast<QTcpSocket *>(sender());
qDebug() << "client out!";
ui->textEditRev->insertPlainText("客户端断开\n");
//网络资源回收,这个必须在判断客户端对象是否为空前面
tmpSock->deleteLater();
qDebug() << ui->comboBoxChildren->count();
//判断myComboBox是否为空,若为空则将发送按钮设置为不可用
if(ui->comboBoxChildren->count() == 0){
ui->btnSend->setEnabled(false);
}
}
//myComboBox槽函数
void Widget::myComboBox_refresh()
{
//找到所有server对象的子对象QTcpSocketClients并遍历
ui->comboBoxChildren->clear();
QList<QTcpSocket*> tcpSocketClients = server->findChildren<QTcpSocket*>();
for(QTcpSocket* tmp:tcpSocketClients){
//添加comboBox子项
ui->comboBoxChildren->addItem(QString::number(tmp->peerPort()));
}
ui->comboBoxChildren->addItem("all");
}
//客户端状态槽函数
void Widget::mstateChanged(QAbstractSocket::SocketState socketState)
{
//myComboBox选项序号
int tmpIndex;
//通过信号发送者找到发送者对象
QTcpSocket *tmpSock = qobject_cast<QTcpSocket *>(sender());
//qDebug() << "client out In state:" << socketState;
switch(socketState){
//case QAbstractSocket::UnconnectedState:
case QAbstractSocket::ClosingState:
//ui->textEditRev->insertPlainText("客户端断开\n");
tmpIndex = ui->comboBoxChildren->findText(QString::number(tmpSock->peerPort()));
ui->comboBoxChildren->removeItem(tmpIndex);
//释放网络资源,防止myComboBox中遗留选项
tmpSock->deleteLater();
break;
//case QAbstractSocket::ConnectingState:
case QAbstractSocket::ConnectedState:
//ui->textEditRev->insertPlainText("客户端接入\n");
break;
}
}
//发送按钮槽函数
void Widget::on_btnSend_clicked()
{
//找到所有server对象的子对象QTcpSocketClients并遍历
QList<QTcpSocket*> tcpSocketClients = server->findChildren<QTcpSocket*>();
//判断客户端对象是否为空,避免因为myComobox刷新不及时导致客户端访问越界
if(tcpSocketClients.isEmpty()){
QMessageBox msgBox;
msgBox.setWindowTitle("发送错误");
msgBox.setText("无已连接的客户端");
msgBox.exec();
ui->btnSend->setEnabled(false);
return;
}
//当用户不选择all,向所有客户端发送数据的时候
if(ui->comboBoxChildren->currentText() != "all"){
//根据用户选择,找到指定客户端进行通信,通过currentName进行查找,若peerPort与当前选择的currentName相同,则向该客户端发送
QString currentName = ui->comboBoxChildren->currentText();
for(QTcpSocket* tmp : tcpSocketClients){
if(QString::number(tmp->peerPort()) == currentName){
tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());
}
}
}else{
//遍历所有子客户端,并一一调用write函数,向所有客户端发送消息
for(QTcpSocket* tmp:tcpSocketClients){
tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());
}
}
}
//comboBox变化槽函数
void Widget::on_comboBoxChildren_activated(int index)
{
childIndex = index;
qDebug() << index;
}
//停止监听槽函数
void Widget::on_btnStopListen_clicked()
{
//找到所有server对象的子对象QTcpSocketClients并遍历
QList<QTcpSocket*> tcpSocketClients = server->findChildren<QTcpSocket*>();
for(QTcpSocket* tmp:tcpSocketClients){
//关闭客户端连接通道
tmp->close();
}
//关闭server
server->close();
//恢复按钮状态
ui->btnListen->setEnabled(true);
ui->btnLineOut->setEnabled(false);
ui->btnStopListen->setEnabled(false);
ui->btnSend->setEnabled(false);
}
//断开连接槽函数
void Widget::on_btnLineOut_clicked()
{
on_btnStopListen_clicked();
delete server;
this->close();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer>
#include "mycombobox.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
QTcpServer *server;
public slots:
void on_newClient_conect();
//数据接收槽函数
void on_readyRead_handler();
//连接断开槽函数
void mdisconnected();
//客户端状态槽函数
void mstateChanged(QAbstractSocket::SocketState);
//myComboBox槽函数
void myComboBox_refresh();
private slots:
//开始监听按钮槽函数
void on_btnListen_clicked();
//发送槽函数
void on_btnSend_clicked();
//myComboBox点击槽函数
void on_comboBoxChildren_activated(int index);
void on_btnStopListen_clicked();
void on_btnLineOut_clicked();
private:
Ui::Widget *ui;
int childIndex;
};
#endif // WIDGET_H
mycombobox.cpp
#include "mycombobox.h"
#include <QMouseEvent>
MyComboBox::MyComboBox(QWidget *parent) : QComboBox(parent)
{
}
void MyComboBox::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::LeftButton){
emit on_ComboBox_clicked();
}
QComboBox::mousePressEvent(e);
}
mycombobox.h
#ifndef MYCOMBOBOX_H
#define MYCOMBOBOX_H
#include <QComboBox>
#include <QWidget>
//自定义ComboBox控件实现点击刷新
class MyComboBox : public QComboBox
{
Q_OBJECT
public:
MyComboBox(QWidget *parent);
protected:
void mousePressEvent(QMouseEvent *e) override;
signals:
void on_ComboBox_clicked();
};
#endif // MYCOMBOBOX_H
5 TCP客户端项目开发
main.c
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QString>
#include <QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//关联窗口和子组件同步变大变小
this->setLayout(ui->verticalLayout);
//创建客户端套接字
client = new QTcpSocket(this);
//数据到达信号与槽的连接
connect(client,SIGNAL(readyRead()),this,SLOT(mRead_data_from_server()));
//设置按钮状态
ui->btnDisconnect->setEnabled(false);
ui->btnSend->setEnabled(false);
}
Widget::~Widget()
{
delete ui;
}
//连接按键槽函数
void Widget::on_btnConect_clicked()
{
//超时定时器
timer = new QTimer(this);
//超时触发
timer->setSingleShot(true);
//超时时间5s
timer->setInterval(5000);
//客户端连接主机
client->connectToHost(ui->lineEditIpAddr->text(),ui->lineEditPort->text().toInt());
//客户端连接连接信号与槽实现
connect(client,SIGNAL(connected()),this,SLOT(onConnected()));
//客户端连接错误信号与槽实现
connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(onerror(QAbstractSocket::SocketError)));
//定时器超时信号与槽实现
connect(timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
//整个窗口不可用
this->setEnabled(false);
timer->start();
}
//发送按键槽函数
void Widget::on_btnSend_clicked()
{
QByteArray sendData = ui->textEditSend->toPlainText().toUtf8();
//发送数据
client->write(sendData);
mInsertTextByColor(Qt::red,sendData + "\n");
}
//数据到达槽函数实现
void Widget::mRead_data_from_server()
{
//光标定位到尾部
ui->textEditRev->moveCursor(QTextCursor::End);
ui->textEditRev->ensureCursorVisible();
QByteArray revData = client->readAll();
mInsertTextByColor(Qt::black,revData + "\n");
}
//断开连接槽函数
void Widget::on_btnDisconnect_clicked()
{
client->close();
ui->textEditRev->append("终止连接");
//设置各个按钮状态
ui->btnConect->setEnabled(true);
ui->lineEditIpAddr->setEnabled(true);
ui->lineEditPort->setEnabled(true);
ui->btnDisconnect->setEnabled(false);
}
//新客户端接入槽函数实现
void Widget::onConnected()
{
//超时定时器停止
timer->stop();
//整个窗口可用
this->setEnabled(true);
//设置各个按钮状态
ui->textEditRev->append("连接成功");
ui->btnConect->setEnabled(false);
ui->btnDisconnect->setEnabled(true);
ui->lineEditIpAddr->setEnabled(false);
ui->lineEditPort->setEnabled(false);
ui->btnSend->setEnabled(true);
}
void Widget::onerror(QAbstractSocket::SocketError error)
{
qDebug() << "连接错误:" << error;
ui->textEditRev->insertPlainText("连接出问题了:" + client->errorString());
this->setEnabled(true);
on_btnDisconnect_clicked();
}
void Widget::onTimeout()
{
ui->textEditRev->insertPlainText("连接超时");
//放弃当前连接
client->abort();
//整个窗口可用
this->setEnabled(true);
}
//修改字体颜色并显示
void Widget::mInsertTextByColor(Qt::GlobalColor color,QString str)
{
//设置字体颜色
QTextCursor cursor = ui->textEditRev->textCursor();
QTextCharFormat format;
format.setForeground(QBrush(QColor(color)));
cursor.setCharFormat(format);
//插入数据
cursor.insertText(str);
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QTcpSocket>
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
//连接按钮槽函数实现
void on_btnConect_clicked();
//发送按钮槽函数实现
void on_btnSend_clicked();
//接收数据槽函数实现
void mRead_data_from_server();
//断开连接槽函数实现
void on_btnDisconnect_clicked();
//新客户端接入槽函数实现
void onConnected();
//客户端连接错误槽函数实现
void onerror(QAbstractSocket::SocketError);
//连接超时定时器槽函数实现
void onTimeout();
private:
Ui::Widget *ui;
//客户端套接字定义
QTcpSocket *client;
//连接超时定时器定义
QTimer *timer;
//修改字体颜色并显示
void mInsertTextByColor(Qt::GlobalColor color,QString str);
};
#endif // WIDGET_H
项目到此结束
更多推荐



所有评论(0)