【Qt网络编程基础】Tcp服务器和客户端(只支持一对一)

目录

一、编写思路

1、服务器

总体思路

详细思路

1. 构造函数 (Widget::Widget)

2. 启动监听 (Widget::on_btn_start_clicked)

3. 停止监听 (Widget::on_btn_cease_clicked)

4. 发送消息 (Widget::on_btn_info_clicked)

5. 接收消息 (Widget::receive_message)

6. 处理客户端连接状态变化 (Widget::handler_client_changed)

7. 处理新的客户端连接 (Widget::handler_newConnection)

2、客户端

总体思路

详细思路

1. 初始化客户端对象

2. 处理“连接服务端”按钮点击事件

3. 处理“断开服务端”按钮点击事件

4. 处理“发送消息”按钮点击事件

5. 处理接收到的消息

6. 处理连接状态变化

二、实现效果

1、服务器

2、客户端

三、完整代码

1、服务器

widget.h

widget.cpp

2、客户端

widget.h

widget.cpp



如需咨询请添加个人微信:a15135158368

欢迎叨扰,多多交流


一、编写思路

1、服务器

总体思路

/* 构建服务器的步骤* 1. 实例化服务器对象--QTcpServer*    相当于:socket* 2. 进入监听状态--listen*    相当于:bind + listen* 3. 监测客户端连接--newConnection*    newConnection信号* 4. 获得客户端连接--nextPendingConnection*    相当于:accept* 5. 读取客户端消息--readAll*    相当于:recv* 6. 发送数据--write*    相当于:send* 7. 关闭连接--disconnectFromHost*    相当于:close*/

详细思路

1. 构造函数 (Widget::Widget)

目的

  • 初始化窗口部件。

  • 创建并配置TCP服务器对象。

  • 连接信号与槽。

关键代码段

Widget::Widget(QWidget *parent): QWidget(parent)  // 调用基类构造函数, ui(new Ui::Widget)  // 初始化UI对象
{ui->setupUi(this);  // 设置UI界面this->setWindowTitle("服务器");  // 设置窗口标题this->resize(1024, 960);  // 设置窗口大小
​// 创建QTcpServer对象tcp_server = new QTcpServer(this);
​// 连接QTcpServer的newConnection信号到槽函数connect(tcp_server, &QTcpServer::newConnection, this, &Widget::handler_newConnection);
​// QT4写法(不推荐):老式信号与槽连接// connect(tcpServer, SIGNAL(newConnection()), this, SLOT(handler_newConnection()));
}
2. 启动监听 (Widget::on_btn_start_clicked)

目的

  • 启动TCP服务器,开始监听客户端连接请求。

  • 绑定IP地址和端口号。

关键代码段

void Widget::on_btn_start_clicked()
{// 使TCP服务器进入监听状态if (tcp_server->listen(QHostAddress(IP), PORT)){ui->te_content->append("服务器开始监听...");  // 显示成功消息}else{ui->te_content->append("服务器监听失败");  // 显示失败消息}
}
3. 停止监听 (Widget::on_btn_cease_clicked)

目的

  • 停止TCP服务器的监听。

  • 关闭服务器连接。

关键代码段

void Widget::on_btn_cease_clicked()
{tcp_server->close();  // 关闭TCP服务器ui->te_content->append("服务器已停止监听");  // 显示停止消息// 服务器关闭后,更新UI按钮状态
}
4. 发送消息 (Widget::on_btn_info_clicked)

目的

  • 向所有已连接的客户端发送消息。

关键代码段

void Widget::on_btn_info_clicked()
{// 获取所有已连接的客户端QList<QTcpSocket*> clients = tcp_server->findChildren<QTcpSocket*>();
​// 遍历每个客户端for (int i = 0; i < clients.length(); i++){QTcpSocket *client = clients[i];
​// 检查客户端的连接状态if (client->state() == QAbstractSocket::ConnectedState){// 发送消息client->write(ui->le_info->text().toUtf8());}else{// 如果客户端未连接,显示提示信息ui->te_content->append("客户端未连接,无法发送消息");}}
}
5. 接收消息 (Widget::receive_message)

目的

  • 处理接收到的客户端消息,并在文本框中显示。

关键代码段

void Widget::receive_message()
{QTcpSocket *client_socket = qobject_cast<QTcpSocket*>(sender());  // 获取发信的客户端套接字if (client_socket){QByteArray data = client_socket->readAll();  // 读取客户端发送的数据ui->te_content->append("客户端 : " + QString(data));  // 显示消息}
}
6. 处理客户端连接状态变化 (Widget::handler_client_changed)

目的

  • 处理客户端连接状态的变化,例如断开连接或连接成功。

  • 更新UI按钮状态。

关键代码段

void Widget::handler_client_changed(QAbstractSocket::SocketState socket_state)
{QTcpSocket *client_socket = (QTcpSocket*)sender();  // 获取发信的客户端套接字
​if (!client_socket) return;
​// 根据连接状态进行处理switch (socket_state){case QAbstractSocket::UnconnectedState:  // 客户端断开连接ui->te_content->append("客户端断开连接");  // 显示断开连接信息client_socket->deleteLater();  // 删除客户端套接字对象ui->btn_start->setEnabled(true);  // 启用“开始监听”按钮ui->btn_cease->setEnabled(false);  // 禁用“停止监听”按钮ui->btn_info->setEnabled(false);  // 禁用“发送消息”按钮break;
​case QAbstractSocket::ConnectedState:  // 客户端已连接ui->btn_start->setEnabled(false);  // 禁用“开始监听”按钮ui->btn_cease->setEnabled(true);  // 启用“停止监听”按钮ui->btn_info->setEnabled(true);  // 启用“发送消息”按钮ui->te_content->append("客户端已连接");  // 显示连接成功信息break;
​default:break;}
}
7. 处理新的客户端连接 (Widget::handler_newConnection)

目的

  • 处理新客户端的连接请求。

  • 获取客户端的IP地址和端口号。

  • 连接相关的信号和槽,处理客户端的消息和状态变化。

关键代码段

void Widget::handler_newConnection()
{// 获取新的客户端连接QTcpSocket *client_socket = tcp_server->nextPendingConnection();
​// 错误处理:检查是否成功获取客户端连接if (client_socket == nullptr){ui->te_content->append("错误:无法获取客户端连接");  // 显示错误信息qDebug() << "Error: Failed to get new client connection.";return;  // 获取失败,直接返回}
​ui->btn_start->setEnabled(false);  // 禁用“开始监听”按钮ui->btn_cease->setEnabled(true);  // 启用“停止监听”按钮ui->btn_info->setEnabled(true);  // 启用“发送消息”按钮
​// 获取客户端的IP地址和端口号QString ip_addr = client_socket->peerAddress().toString();quint16 port = client_socket->peerPort();
​// 错误处理:检查是否成功获取IP地址和端口号if (ip_addr.isEmpty() || port == 0) {ui->te_content->append("错误:无法获取客户端的IP地址或端口号");  // 显示错误信息qDebug() << "Error: Failed to get client's IP address or port.";client_socket->disconnectFromHost();  // 断开连接client_socket->deleteLater();  // 删除客户端套接字对象return;  // 获取失败,直接返回}
​// 打印客户端的IP地址和端口号ui->te_content->append("客户端的IP地址为: " + ip_addr);ui->te_content->append("客户端的端口号为: " + QString::number(port));
​// 连接信号与槽,处理客户端的消息和状态变化connect(client_socket, &QTcpSocket::readyRead, this, &Widget::receive_message);connect(client_socket, &QTcpSocket::stateChanged, this, &Widget::handler_client_changed);
​// 错误处理:处理客户端的异常断开情况connect(client_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::errorOccurred),this, [=](QAbstractSocket::SocketError socketError){ui->te_content->append("错误:客户端连接错误,错误代码:" + QString::number(socketError));  // 显示错误信息qDebug() << "Client connection error, error code: " << socketError;client_socket->deleteLater();  // 删除客户端套接字对象});
}

2、客户端

总体思路

/** 客户端构建步骤:* 1、实例化QTcpSocket对象* 2、连接服务器--connectToHost* 3、判断是否连接成功--waitForConnected* 4、连接对端接收信号--readyRead* 5、发送数据--write* 6、关闭连接--disconnectFromHost*/

详细思路

1. 初始化客户端对象
  • 步骤

    创建 QTcpSocket 对象,设置 UI 界面,并连接信号与槽函数。

  • 关键代码段:

    Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
    {ui->setupUi(this);  // 设置UI界面this->setWindowTitle("-客户端-");  // 设置窗口标题this->resize(1024, 960);  // 设置窗口大小
    ​tcp_socket = new QTcpSocket(this);  // 创建QTcpSocket对象
    ​// 连接QTcpSocket的信号与槽函数connect(tcp_socket, &QTcpSocket::readyRead, this, &Widget::receiveMessage);connect(tcp_socket, &QTcpSocket::stateChanged, this, &Widget::mStateChanged);
    }
  • 详细说明:

    • ui->setupUi(this): 初始化UI界面。

    • tcp_socket = new QTcpSocket(this): 创建TCP套接字对象,用于与服务器进行通信。

    • connect(): 连接QTcpSocket的信号readyReadstateChanged到对应的槽函数receiveMessagemStateChanged

2. 处理“连接服务端”按钮点击事件
  • 步骤

    调用 QTcpSocketconnectToHost() 方法来连接服务器。

  • 关键代码段:

    void Widget::on_btn_start_clicked()
    {// 尝试连接到指定的IP地址和端口号tcp_socket->connectToHost(QHostAddress(IP), PORT);
    }
  • 详细说明:

    • tcp_socket->connectToHost(QHostAddress(IP), PORT): 连接到指定的IP地址和端口号。此函数异步执行,连接成功或失败将触发相应的信号。

3. 处理“断开服务端”按钮点击事件
  • 步骤

    调用 QTcpSocketdisconnectFromHost() 方法断开与服务器的连接。

  • 关键代码段:

    void Widget::on_btn_cease_clicked()
    {// 断开与服务器的连接tcp_socket->disconnectFromHost();
    }
  • 详细说明

    • tcp_socket->disconnectFromHost(): 断开与服务器的连接,释放资源。

4. 处理“发送消息”按钮点击事件
  • 步骤

    检查客户端是否已连接到服务器,然后发送消息。

  • 关键代码段:

    void Widget::on_btn_info_clicked()
    {// 检查当前是否处于连接状态if (tcp_socket->state() == QAbstractSocket::ConnectedState){// 发送消息到服务器tcp_socket->write(ui->le_info->text().toUtf8());}else{// 如果未连接,显示提示信息ui->te_content->append("请先连接服务器!");}
    }
  • 详细说明

    • tcp_socket->state() == QAbstractSocket::ConnectedState: 确保在发送消息之前客户端已连接到服务器。

    • tcp_socket->write(): 发送消息到服务器。消息需转换为字节数组(QByteArray)。

5. 处理接收到的消息
  • 步骤

    读取服务器发送的数据并显示在文本框中。

  • 关键代码段:

    void Widget::receiveMessage()
    {// 读取所有接收到的数据,并显示在文本框中ui->te_content->append("服务器发送的消息:" + tcp_socket->readAll());
    }
  • 详细说明:

    • tcp_socket->readAll(): 读取从服务器接收到的所有数据,并以字符串形式显示在文本框中。

6. 处理连接状态变化
  • 步骤

    根据连接状态的变化更新UI和显示状态信息。

  • 关键代码段:

    void Widget::mStateChanged(QAbstractSocket::SocketState socketstate)
    {switch (socketstate){case QAbstractSocket::UnconnectedState:ui->te_content->append("与服务器断开连接");ui->btn_start->setEnabled(true);   // 允许重新连接ui->btn_cease->setEnabled(false);  // 禁用断开按钮ui->btn_info->setEnabled(false);   // 禁用发送按钮break;
    ​case QAbstractSocket::ConnectedState:ui->te_content->append("与服务器建立连接");ui->btn_start->setEnabled(false);  // 禁用连接按钮ui->btn_cease->setEnabled(true);   // 允许断开ui->btn_info->setEnabled(true);    // 允许发送消息break;
    ​case QAbstractSocket::HostLookupState:ui->te_content->append("正在查找主机...");break;
    ​case QAbstractSocket::ConnectingState:ui->te_content->append("正在连接服务器...");break;
    ​case QAbstractSocket::ClosingState:ui->te_content->append("正在关闭连接...");break;
    ​default:// 显示未知状态的调试信息qDebug() << "未知的错误, 当前状态: " << socketstate;break;}
    }
  • 详细说明

    • 根据 socketstate 的不同值更新UI和显示状态信息。

    • QAbstractSocket::UnconnectedState: 客户端已断开连接。

    • QAbstractSocket::ConnectedState: 客户端已连接到服务器。

    • QAbstractSocket::HostLookupState, QAbstractSocket::ConnectingState, QAbstractSocket::ClosingState: 其他状态信息。

二、实现效果

1、服务器

2、客户端

三、完整代码

1、服务器

widget.h

#ifndef WIDGET_H
#define WIDGET_H
​
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>  // TCP服务器和客户端都使用
​
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
​
// Widget类继承自QWidget,是一个用于实现TCP服务器的界面
class Widget : public QWidget
{Q_OBJECT
​
public:// 构造函数,初始化Widget对象Widget(QWidget *parent = nullptr);
​// 析构函数,清理资源~Widget();
​
private slots:// 处理“开始”按钮点击事件的槽函数void on_btn_start_clicked();
​// 处理“停止”按钮点击事件的槽函数void on_btn_cease_clicked();
​// 处理“信息”按钮点击事件的槽函数void on_btn_info_clicked();
​// 处理接收到消息的槽函数void receive_message();
​// 处理客户端连接状态变化的槽函数void handler_client_changed(QAbstractSocket::SocketState socket_state);
​// 处理新的连接请求的槽函数void handler_newConnection();
​
private:// UI对象指针,用于管理界面组件Ui::Widget *ui;
​// TCP服务器对象指针QTcpServer *tcp_server;
};
​
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
​
const char* IP = "127.0.0.1";    // 定义IP地址常量,表示本地地址
const unsigned int PORT = 8888;  // 定义端口号常量,表示服务器监听的端口
​
/* 构建服务器的步骤* 1. 实例化服务器对象--QTcpServer*    相当于:socket* 2. 进入监听状态--listen*    相当于:bind + listen* 3. 监测客户端连接--newConnection*    newConnection信号* 4. 获得客户端连接--nextPendingConnection*    相当于:accept* 5. 读取客户端消息--readAll*    相当于:recv* 6. 发送数据--write*    相当于:send* 7. 关闭连接--disconnectFromHost*    相当于:close*/
​
/** te_content* btn_start btn_cease* btn_info le_info*/
​
/************************************************************ @函数名:Widget* @功  能:构造函数---创建服务端对象,与客户端连接* @参  数:parent---父对象* @返回值:无*********************************************************/
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)  // 初始化UI对象
{ui->setupUi(this);  // 设置UI界面this->setWindowTitle("服务器");  // 设置窗口标题this->resize(1024, 960);  // 设置窗口大小
​// 创建QTcpServer对象,用于监听客户端连接tcp_server = new QTcpServer(this);
​// 连接QTcpServer的newConnection信号到处理新的连接的槽函数connect(tcp_server, &QTcpServer::newConnection, this, &Widget::handler_newConnection);
​// QT4写法(不推荐使用):连接信号与槽的老式写法// connect(tcpServer, SIGNAL(newConnection()), this, SLOT(handler_newConnection()));
}
​
Widget::~Widget()
{delete ui;  // 删除UI对象,释放资源
}
​
/************************************************************ @函数名:on_btn_start_clicked()* @功  能:按钮"开始监听"的槽函数,开始监听服务器,绑定IP和端口* @参  数:无* @返回值:无*********************************************************/
void Widget::on_btn_start_clicked()
{// 进入监听状态,绑定IP和端口if (tcp_server->listen(QHostAddress(IP), PORT)){ui->te_content->append("服务器开始监听...");  // 在文本框中显示成功消息}else{ui->te_content->append("服务器监听失败");  // 在文本框中显示失败消息}
}
​
/************************************************************ @函数名:on_btn_cease_clicked()* @功  能:按钮"停止监听"的槽函数,停止监听并关闭服务器* @参  数:无* @返回值:无*********************************************************/
void Widget::on_btn_cease_clicked()
{tcp_server->close();  // 关闭TCP服务器ui->te_content->append("服务器已停止监听");  // 在文本框中显示停止消息// 服务器关闭后,相关UI按钮状态更新
}
​
/************************************************************ @函数名:on_btn_info_clicked()* @功  能:按钮"发送消息"的槽函数,将文本信息发送给所有客户端* @参  数:无* @返回值:无*********************************************************/
void Widget::on_btn_info_clicked()
{// 获取所有已连接的客户端QList<QTcpSocket*> clients = tcp_server->findChildren<QTcpSocket*>();
​// 遍历每个客户端for (int i = 0; i < clients.length(); i++){QTcpSocket *client = clients[i];
​// 检查客户端的连接状态if (client->state() == QAbstractSocket::ConnectedState){// 发送数据client->write(ui->le_info->text().toUtf8());}else{// 如果客户端未连接,输出信息提示ui->te_content->append("客户端未连接,无法发送消息");}}
}
​
/************************************************************ @函数名:receive_message* @功  能:槽函数:接收客户端发送的消息并在文本框中显示* @参  数:无* @返回值:无*********************************************************/
void Widget::receive_message()
{QTcpSocket *client_socket = qobject_cast<QTcpSocket*>(sender());  // 获取发信的客户端套接字if (client_socket){QByteArray data = client_socket->readAll();  // 读取客户端发送的所有数据ui->te_content->append("客户端 : " + QString(data));  // 在文本框中显示消息}
}
​
/************************************************************ @函数名:handler_client_changed* @功  能:槽函数:处理客户端连接状态的改变* @参  数:socketState---客户端连接状态* @返回值:无*********************************************************/
void Widget::handler_client_changed(QAbstractSocket::SocketState socket_state)
{QTcpSocket *client_socket = (QTcpSocket*)sender();  // 获取发信的客户端套接字
​if (!client_socket) return;
​// 根据连接状态进行处理switch (socket_state){case QAbstractSocket::UnconnectedState:  // 客户端断开连接ui->te_content->append("客户端断开连接");  // 在文本框中显示断开连接信息client_socket->deleteLater();  // 删除客户端套接字对象ui->btn_start->setEnabled(true);  // 启用“开始监听”按钮ui->btn_cease->setEnabled(false);  // 禁用“停止监听”按钮ui->btn_info->setEnabled(false);  // 禁用“发送消息”按钮break;
​case QAbstractSocket::ConnectedState:  // 客户端已连接ui->btn_start->setEnabled(false);  // 禁用“开始监听”按钮ui->btn_cease->setEnabled(true);  // 启用“停止监听”按钮ui->btn_info->setEnabled(true);  // 启用“发送消息”按钮ui->te_content->append("客户端已连接");  // 在文本框中显示连接成功信息break;
​default:break;}
}
​
/************************************************************ @函数名:handler_newConnection* @功  能:槽函数:当有新的客户端连接时,打印客户端IP和端口* @参  数:无* @返回值:无*********************************************************/
void Widget::handler_newConnection()
{// 获取新的客户端连接QTcpSocket *client_socket = tcp_server->nextPendingConnection();
​// 错误处理:检查是否成功获取客户端连接if (client_socket == nullptr){ui->te_content->append("错误:无法获取客户端连接");  // 在文本框中显示错误信息qDebug() << "Error: Failed to get new client connection.";return;  // 如果获取失败,直接返回}
​ui->btn_start->setEnabled(false);  // 禁用“开始监听”按钮ui->btn_cease->setEnabled(true);  // 启用“停止监听”按钮ui->btn_info->setEnabled(true);  // 启用“发送消息”按钮
​// 获取客户端的IP地址和端口号QString ip_addr = client_socket->peerAddress().toString();quint16 port = client_socket->peerPort();
​// 错误处理:检查是否成功获取IP地址和端口号if (ip_addr.isEmpty() || port == 0) {ui->te_content->append("错误:无法获取客户端的IP地址或端口号");  // 在文本框中显示错误信息qDebug() << "Error: Failed to get client's IP address or port.";client_socket->disconnectFromHost();  // 断开连接client_socket->deleteLater();  // 删除客户端套接字对象return;  // 如果获取失败,直接返回}
​// 打印客户端的IP地址和端口号ui->te_content->append("客户端的IP地址为: " + ip_addr);ui->te_content->append("客户端的端口号为: " + QString::number(port));
​// 处理接收数据的槽函数connect(client_socket, &QTcpSocket::readyRead, this, &Widget::receive_message);
​// 处理连接状态变化的槽函数connect(client_socket, &QTcpSocket::stateChanged, this, &Widget::handler_client_changed);
​// 错误处理:处理客户端的异常断开情况connect(client_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::errorOccurred),this, [=](QAbstractSocket::SocketError socketError){ui->te_content->append("错误:客户端连接错误,错误代码:" + QString::number(socketError));  // 显示错误信息qDebug() << "Client connection error, error code: " << socketError;client_socket->deleteLater();  // 删除客户端套接字对象});
}

2、客户端

widget.h

#ifndef WIDGET_H
#define WIDGET_H
​
#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>
​
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
​
// 定义Widget类,继承自QWidget
class Widget : public QWidget
{Q_OBJECT  // Qt的元对象系统宏,支持信号和槽
​
public:// 构造函数:初始化Widget对象// @param parent:父对象指针,默认为nullptrWidget(QWidget *parent = nullptr);
​// 析构函数:释放资源~Widget();
​
private slots:// 槽函数:处理点击"开始"按钮事件void on_btn_start_clicked();
​// 槽函数:处理点击"停止"按钮事件void on_btn_cease_clicked();
​// 槽函数:处理点击"发送信息"按钮事件void on_btn_info_clicked();
​// 槽函数:接收并处理来自客户端的消息void receive_message();
​// 槽函数:处理TCP连接状态改变事件// @param socketstate:连接状态void state_changed(QAbstractSocket::SocketState socketstate);
​
private:Ui::Widget *ui;  // 指向UI界面的指针
​QTcpSocket *tcp_socket;  // 指向TCP套接字对象的指针
};
​
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <QDebug>
​
const char* IP = "127.0.0.1";  // 定义服务器的IP地址
const unsigned int PORT = 8888;  // 定义服务器的端口号
​
/** 客户端构建步骤:* 1、实例化QTcpSocket对象* 2、连接服务器--connectToHost* 3、判断是否连接成功--waitForConnected* 4、连接对端接收信号--readyRead* 5、发送数据--write* 6、关闭连接--disconnectFromHost*/
​
/** te_content:文本框,用于显示接收到的消息和状态信息* btn_start:按钮,用于启动与服务器的连接* btn_cease:按钮,用于断开与服务器的连接* btn_info:按钮,用于发送消息到服务器* le_info:文本框,用于输入待发送的消息*/
​
/************************************************************ @函数名:Widget* @功  能:构造函数,初始化客户端界面和TCP套接字对象* @参  数:parent---父对象* @返回值:无*********************************************************/
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);  // 设置UI界面this->setWindowTitle("-客户端-");  // 设置窗口标题this->resize(1024, 960);  // 设置窗口大小
​tcp_socket = new QTcpSocket(this);  // 创建QTcpSocket对象
​// 连接QTcpSocket的信号与槽函数connect(tcp_socket, &QTcpSocket::readyRead, this, &Widget::receive_message);connect(tcp_socket, &QTcpSocket::stateChanged, this, &Widget::state_changed);
​// QT4写法(不推荐):老式信号与槽连接// connect(tcp_socket, SIGNAL(readyRead()), this, SLOT(receive_message()));// connect(tcp_socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),//         this, SLOT(state_changed(QAbstractSocket::SocketState)));
}
​
/************************************************************ @函数名:~Widget* @功  能:析构函数,释放资源* @参  数:无* @返回值:无*********************************************************/
Widget::~Widget()
{delete ui;  // 删除UI对象
}
​
/************************************************************ @函数名:on_btn_start_clicked()* @功  能:处理点击“连接服务端”按钮的事件* @参  数:无* @返回值:无*********************************************************/
void Widget::on_btn_start_clicked()
{// 尝试连接到指定的IP地址和端口号tcp_socket->connectToHost(QHostAddress(IP), PORT);
}
​
/************************************************************ @函数名:on_btn_cease_clicked()* @功  能:处理点击“断开服务端”按钮的事件* @参  数:无* @返回值:无*********************************************************/
void Widget::on_btn_cease_clicked()
{// 断开与服务器的连接tcp_socket->disconnectFromHost();
}
​
/************************************************************ @函数名:on_btn_info_clicked()* @功  能:处理点击“发送消息”按钮的事件*        发送消息到服务器,只有在连接状态时才允许发送* @参  数:无* @返回值:无*********************************************************/
void Widget::on_btn_info_clicked()
{// 检查当前是否处于连接状态if (tcp_socket->state() == QAbstractSocket::ConnectedState){// 发送消息到服务器tcp_socket->write(ui->le_info->text().toUtf8());}else{// 如果未连接,显示提示信息ui->te_content->append("请先连接服务器!");}
}
​
/************************************************************ @函数名:receive_message* @功  能:槽函数---接收服务器发送的数据,并显示在文本框中* @参  数:无* @返回值:无*********************************************************/
void Widget::receive_message()
{// 读取所有接收到的数据,并显示在文本框中ui->te_content->append("服务器发送的消息:" + tcp_socket->readAll());
}
​
/************************************************************ @函数名:state_changed* @功  能:槽函数---处理客户端连接状态的改变* @参  数:socketstate---当前连接状态* @返回值:无*********************************************************/
void Widget::state_changed(QAbstractSocket::SocketState socketstate)
{// 根据不同的连接状态更新UI和显示状态信息switch (socketstate){case QAbstractSocket::UnconnectedState:ui->te_content->append("与服务器断开连接");ui->btn_start->setEnabled(true);   // 允许重新连接ui->btn_cease->setEnabled(false);  // 禁用断开按钮ui->btn_info->setEnabled(false);   // 禁用发送按钮break;
​case QAbstractSocket::ConnectedState:ui->te_content->append("与服务器建立连接");ui->btn_start->setEnabled(false);  // 禁用连接按钮ui->btn_cease->setEnabled(true);   // 允许断开ui->btn_info->setEnabled(true);    // 允许发送消息break;
​case QAbstractSocket::HostLookupState:ui->te_content->append("正在查找主机...");break;
​case QAbstractSocket::ConnectingState:ui->te_content->append("正在连接服务器...");break;
​case QAbstractSocket::ClosingState:ui->te_content->append("正在关闭连接...");break;
​default:// 显示未知状态的调试信息qDebug() << "未知的错误, 当前状态: " << socketstate;break;}
}

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

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

相关文章

了解Redis集群概念,集群如何选举主节点

请给胡广一个免费的三连吗&#xff1f;感谢&#xff01; 1. Redis集群 1.1 集群概念 Redis主从架构和Redis集群架构是两种不同的概念&#xff0c;大家刚接触Redis时经常弄混淆。胡广给大家贴下Redis官网对两者的解释。 &#xff08;1&#xff09;Redis主从架构 Redis主从实…

通讯录

在写一个程序前需要了解的知识&#xff0c;需要对通讯录的流程了如指掌&#xff0c;才能写出一个完整的程序 。 写一个主函数&#xff0c;里面包含菜单、对菜单的选择、以及循环。创建个人信息结构体&#xff0c;多人构成的结构体数组。分析每一个函数&#xff1a; 1).增加信…

图文教程 | 2024年IDEA安装使用教程,JDK简易下载方法

前言 &#x1f4e2;博客主页&#xff1a;程序源⠀-CSDN博客 &#x1f4e2;欢迎点赞&#x1f44d;收藏⭐留言&#x1f4dd;如有错误敬请指正&#xff01; 目录 一、IDEA安装 二、激活 三、JDK安装 四、JDK环境配置 五、验证 一、IDEA安装 进入官网下载&#xff1a; Other…

模拟网络丢包常用方法以及工具

文章目录 背景常用方法代码实现使用方法测试代码 使用网络流量控制工具 常用工具Clumsy 背景 在软件开发过程中&#xff0c;经常需要模拟不同的网络环境来测试应用在不同条件下的表现。 这些模拟可以采用多种方式进行&#xff0c;包括在代码中实现随机丢包、随机延时、乱序&am…

C++ IO流全解析:标准库中的数据处理与文件读写艺术

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;C从入门到精通 目录 一&#xff1a; &#x1f525; C语言的输入与输出 二&#xff1a; &#x1f525; 流是什么 三&#xff1a; &#x1f525; CIO流&#x1f680; 3.1 C标准IO流&#x1f680; ist…

野生动物检测-目标检测数据集(包括VOC格式、YOLO格式)

野生动物检测-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1RHpKHAyRyl0FDD4Up3MOmQ?pwdrbjq 提取码&#xff1a;rbjq数据集信息介绍&#xff1a; 共有 1504 张图像和一一对应的标注文件 标…

QStackedWidget类的使用

本文介绍QStackedWidget类的使用。 StackedWidget控件在Qt应用程序开发过程中用的还是比较多的&#xff0c;配合按钮可以实现多个页面之间相互切换&#xff0c;方便了应用程序的开发&#xff0c;本文简要介绍QStackedWidget类实际使用过程中的常用方法&#xff0c;并给出一个简…

Python画笔案例-042 绘制空心十字架

1、绘制空心十字架 通过 python 的turtle 库绘制空心十字架&#xff0c;如下图&#xff1a; 2、实现代码 绘制空心十字架&#xff0c;以下为实现代码&#xff1a; """空心十字架.py """ import turtledef draw_pattern(length):for _ in range(…

Java 学习中使用文件、网络连接等资源时,未正确关闭资源,导致资源泄漏应该怎么办?

在Java编程中&#xff0c;处理文件、网络连接、数据库连接等资源时&#xff0c;如果没有正确关闭资源&#xff0c;就会发生资源泄漏。资源泄漏会导致系统性能下降、内存占用增加&#xff0c;甚至可能导致程序崩溃&#xff0c;特别是在高负载的系统中。 一、什么是资源泄漏&…

仕考网:哈尔滨2024下半年事业单位招考公告

招聘岗位需求计划 本次计划招聘事业单位工作人员共计588名。具体招聘单位、岗位、人数、条件等情况详见《哈尔滨市2024年下半年事业单位公开招聘工作人员岗位计划表》 年龄要求&#xff1a; 满18周岁(2006年9月18日以前出生)、35(含)周岁以下(1988年9月18日及以后出生) 博士…

基于SpringBoot+Vue的考研学习分享互助平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的考研学习…

企业图纸加密软件哪个最好用?10款常用图纸加密软件强力推荐!

在现代企业中&#xff0c;保护图纸和设计文件的安全性至关重要。以下是十款常用且功能强大的图纸加密软件推荐&#xff0c;帮助企业更好地保护其知识产权和敏感数据。 1. 安秉网盾 安秉网盾凭借其强大的加密技术和灵活的权限管理功能&#xff0c;成为企业保护图纸安全的首选。…

JavaScript高级——函数中的this

1、this是什么&#xff1f; ① 任何函数本质上都是通过某个对象来调用的&#xff0c;如果没有直接指定就是 window 。 ② 所有函数内部都有一个变量 this 。 ③ 它的值是调用函数的当前对象。 2、如何确定 this 的值&#xff1f; ① test&#xff08;&#xff09;&#xff…

强!70.3K star ! 推荐一款功能强大、开源、可视化的性能实时监控系统:Netdata

在当今复杂多变的IT环境中&#xff0c;系统性能的实时监控与分析对于确保业务连续性、系统稳定运行以及快速故障排查至关重要。随着云计算、大数据和微服务架构的普及&#xff0c;对监控系统的要求也日益增高。 今天给大家推荐一款性能监控工具为:Netdata。 它作为一款开源、…

7.测试用例设计方法 + Bug

一、正交实验法 1.使用场景 因果关系比较庞大的情况下&#xff0c;不太适合用因果图判定表&#xff0c;在这种情况下&#xff0c;一般会采用正交实验法。 2.例子&#xff1a; 字符属性设置&#xff08;4个条件&#xff09; 字体很多 字符样式很多 …

appium server gui详细按照步骤

1.安装appium server desktop Appium安装提供两种方式:桌面版和命令行版。其中桌面版又分为 Appium GuI 和 Appium Desktop 。作为初学者&#xff0c;用桌面版&#xff0c;对初学者比较友好。 官网下载地址&#xff1a;Releases appium/appium-desktop GitHubTags appium/…

百度经纬度互转高德经纬度_在线经纬度转换工具

简介说明 在线经纬度转换工具主要功能:百度经纬度转高德经纬度,高德经纬度转百度经纬度,坐标拾取,经纬度反查高德坐标拾取器,坐标拾取,经纬度反查百度坐标拾取器,坐标拾取,经纬度反查地图数据批量收集 操作界面 使用入口> 百度经纬度互转高德经纬度_在线经纬度转换工具

如何让Google收录我的网站?

其实仅仅只是收录&#xff0c;只要在GSC提交网址&#xff0c;等个两三天&#xff0c;一般就能收录&#xff0c;但收录是否会掉&#xff0c;这篇内容收录了是否有展现&#xff0c;排名&#xff0c;就是另外一个课题了&#xff0c;如果不收录&#xff0c;除了说明你的网站有问题&…

阿里云rds数据迁移

记录一下rds数据同步操作,官方文档: 跨阿里云账号迁移RDS实例. 背景:不同阿里云账号的rds中指定数据库迁移. 操作说明: 使用阿里云数据传输服务产品,选择数据迁移.注意是从目标阿里云账号的rds中操作,按照文档操作基本上没有问题. 源阿里云账号设置如上. 需要注意的是需要从源…

计算机网络 ---- 电路交换、报文交换、分组交换

目录 零、前言 一、计算机网络发展初期面临的问题 1.1 电路交换的主要特点【电话网络采用电路交换技术】 1.1.1 电路交换的基本知识介绍 1.1.2 电路交换的优缺点 1.3 报文交换技术的特点【电报网络采用报文交换技术】 1.3.1 报文交换的基本知识介绍 1.3.2 报文交换技术…