Qt实践:TCP服务器和客户端的设计

Qt:5.12.2

Qt Creator:4.11.1

通信方式:TCP\IP

语言:C++

一、TCP Client的设计

客户端的界面UI包含服务器IP、服务器端口、以及一些简单的功能,数据可选ASCLL及HEX格式。当未与服务器建立连接时,该客户端的部分控件设置为禁用。

自动获取本地IP并显示在QLineEdit中(该部分参考了一篇博客,链接在文末)

'getIp()'函数可以根据不同的操作系统获取本地 IP 地址。在 Windows 系统下,通过使用 'QHostInfo::fromName(QHostInfo::localHostName())'获取本地主机信息,并存储在 'vAddressList' 列表中;在非 Windows 系统下,它直接调用 'QNetworkInterface::allAddresses()`'获取所有网络接口信息。然后,遍历地址列表 ('vAddressList'),找到一个有效的 IPv4 地址并存储在 'myipv4Address'变量中。'initialize()`'函数调用 'getIp()`'获取本地 IP 地址,并将其显示在客户端 UI 的 IP 地址输入框 ('ui->ipLineEdit') 中。

QString Client::getIp() {
    QString myipv4Address;

#ifdef _WIN32
    // Windows 系统下获取本地主机信息
    QHostInfo vHostInfo = QHostInfo::fromName(QHostInfo::localHostName());
    QList<QHostAddress> vAddressList = vHostInfo.addresses();
#else
    // 非 Windows 系统下获取所有网络接口信息
    QList<QHostAddress> vAddressList = QNetworkInterface::allAddresses();
#endif

    // 遍历地址列表以查找有效的 IPv4 地址
    for (int i = 0; i < vAddressList.size(); i++) {
        if (!vAddressList.at(i).isNull() &&
            vAddressList.at(i) != QHostAddress::LocalHost &&
            vAddressList.at(i).protocol() == QAbstractSocket::IPv4Protocol) {
            myipv4Address = vAddressList.at(i).toString();
            break;
        }
    }

    return myipv4Address;
}

void Client::initialize() {
    QString localIP = getIp();
    ui->ipLineEdit->setText(localIP);
}

连接服务器

通过两个函数来更新客户端界面和连接状态。'connectToServer()'函数首先检查当前是否已连接到服务器。如果尚未连接,则从 IP 地址输入框和端口号输入框获取目标服务器的 IP 地址和端口号,并尝试连接到目标服务器。连接成功后,显示成功连接的消息框,更新连接状态和发送/接收选项,并启用发送文本框。如果连接失败,则显示连接失败的消息框。'disconnectFromServer()'函数首先检查当前是否已连接到服务器。如果已连接,则断开与服务器的连接,并更新连接状态和发送/接收选项。在断开连接后,禁用发送文本框。

void Client::connectToServer()
{
    // 检查当前是否已连接到服务器
    if (!isConnected) {
        // 从 IP 地址输入框和端口号输入框获取目标服务器的IP地址和端口号
        QString ipAddress = ui->ipLineEdit->text();
        quint16 port = ui->portLineEdit->text().toUShort();

        // 尝试连接到目标服务器
        tcpSocket->connectToHost(QHostAddress(ipAddress), port);

        // 等待连接,最多等待3秒(3000毫秒)
        if (tcpSocket->waitForConnected(3000)) {
            // 连接成功的消息框提示
            QMessageBox::information(this, "Connected", "Successfully connected to server!");
            // 更新连接状态和发送/接收选项
            isConnected = true;
            updateSendOptions(true);
            updateRecvOptions(true);
            // 在成功连接后启用发送文本框
            ui->sendTextEdit->setEnabled(true);
        } else {
            // 连接失败的消息框提示
            QMessageBox::critical(this, "Error", "Connection failed!");
        }
    }
}

void Client::disconnectFromServer()
{
    // 检查当前是否已连接到服务器
    if (isConnected) {
        // 断开与服务器的连接
        tcpSocket->disconnectFromHost();
        // 更新连接状态和发送/接收选项
        isConnected = false;
        updateSendOptions(false);
        updateRecvOptions(false);
        // 在断开连接后禁用发送文本框
        ui->sendTextEdit->setEnabled(false);
    }
}

数据收发逻辑

'sendNewLine()'函数首先检查是否已连接到服务器。如果已连接,则根据当前选择的数据格式(ASCII 或 HEX)从发送区文本框获取数据,并将其发送到服务器。'displayReceivedData()'函数读取从服务器接收到的数据,并根据当前选择的接收数据格式(ASCII 或 HEX)将其显示在接收区文本框中。如果停止显示复选框未选中,则继续显示数据。

void Client::sendNewLine()
{
    // 检查是否已经连接到服务器
    if (isConnected) {
        // 检查当前选择的发送数据格式是否为 HEX 格式
        if (ui->sendFormatComboBox->currentIndex() == 1) { // HEX format
            // 检查发送区文本框是否有数据
            if (!ui->sendTextEdit->toPlainText().isEmpty()) {
                // 获取发送区文本内容,并清理其中的空格等空白字符
                QString hexData = ui->sendTextEdit->toPlainText().simplified(); // Remove spaces
                // 检查处理后的十六进制字符串长度是否为偶数
                if (hexData.size() % 2 != 0) {
                    qDebug() << "Error: Incomplete hex data!";
                    return;
                }

                // 创建字节数组用于存储转换后的字节数据
                QByteArray byteArray;
                byteArray.resize(hexData.length() / 2);

                bool ok;
                // 将十六进制字符串转换为字节数据
                for (int i = 0; i < hexData.length(); i += 2) {
                    QString byte = hexData.mid(i, 2);
                    byteArray[i / 2] = static_cast<char>(byte.toInt(&ok, 16));
                    // 检查转换过程中是否有非法字符
                    if (!ok) {
                        qDebug() << "Error: Invalid hex data!";
                        return;
                    }
                }

                // 发送转换后的字节数据到服务器
                tcpSocket->write(byteArray);
            }
        } else { // ASCII format
            // 检查发送区文本框是否有数据
            if (!ui->sendTextEdit->toPlainText().isEmpty()) {
                // 将文本内容转换为 UTF-8 格式的字节数据,并发送到服务器
                tcpSocket->write(ui->sendTextEdit->toPlainText().toUtf8());
            }
        }
    } else {
        // 如果未连接到服务器,则无法发送数据
        qDebug() << "Not connected to a server. Cannot send data.";
    }
}

void Client::displayReceivedData()
{
    // 读取接收到的数据
    QByteArray receivedData = tcpSocket->readAll();

    QString displayData;
    if (ui->receiveFormatComboBox->currentIndex() == 1) { // HEX format
        // 如果接收格式为 HEX,则将数据以十六进制格式显示
        QString hexData;
        for (int i = 0; i < receivedData.size(); ++i) {
            hexData += QString("%1 ").arg(static_cast<unsigned char>(receivedData.at(i)), 2, 16, QChar('0')).toUpper();
        }
        displayData = hexData;
    } else { // ASCII format
        // 如果接收格式为 ASCII,则直接显示接收到的数据
        displayData = QString::fromUtf8(receivedData);
    }

    if (!ui->stopDisplayCheckBox->isChecked()) {
        // 如果停止显示复选框未选中,则将数据追加到接收区域文本框中
        ui->recvTextEdit->append(displayData);
    }
}

二、TCP Server的设计

服务器部分的设计与客户端类似,以下会提供一些主要部分的代码及注释。

获取IP不再赘述,下面是服务器监听的逻辑

'on_connectButton_clicked()'函数用于启动服务器监听连接请求。首先检查服务器是否已处于监听状态。如果服务器尚未处于监听状态,则从端口号输入框获取端口号,并使用 'tcpServer->listen(QHostAddress::Any, port)`'启动服务器监听。如果启动失败,则显示错误消息。成功启动后,状态标签 ('ui->statusLabel') 显示为 "Server running: Waiting for connection..."。

'on_disconnectButton_clicked()'函数用于停止服务器监听。首先检查服务器是否正在监听。如果服务器正在监听连接,则使用 'tcpServer->close()'停止服务器监听。停止后,状态标签 ('ui->statusLabel') 显示为 "Server stopped."。

void Server::on_connectButton_clicked()
{
    // 启动服务器监听连接请求
    if (!tcpServer->isListening()) {
        quint16 port = ui->portLineEdit->text().toUShort();
        if (!tcpServer->listen(QHostAddress::Any, port)) {
            QMessageBox::critical(this, "Error", "Unable to start the server!");
            return;
        }
        ui->statusLabel->setText("Server running: Waiting for connection...");
    }
}

void Server::on_disconnectButton_clicked()
{
    // 停止服务器监听
    if (tcpServer->isListening()) {
        tcpServer->close();
        ui->statusLabel->setText("Server stopped.");
    }
}

数据收发逻辑

 'on_sendButton_clicked()'用于处理服务器端发送数据。首先检查是否与客户端连接,然后根据发送数据的格式从发送区获取数据并发送到客户端。如果未连接到客户端,则输出错误消息。

'displayReceivedData()'用于显示接收到的数据。它读取从客户端接收到的数据,并根据接收数据的格式(HEX 或 ASCII)将数据显示在接收区域。如果停止显示复选框未选中,则将数据继续到接收区。

void Server::on_sendButton_clicked()
{
    // 检查是否与客户端连接
    if (tcpSocket->state() == QAbstractSocket::ConnectedState) {
        // 检查发送数据的格式
        if (ui->sendFormatComboBox->currentIndex() == 1) { // HEX format
            // 从发送区获取HEX格式的数据并发送
            if (!ui->sendTextEdit->toPlainText().isEmpty()) {
                QString hexData = ui->sendTextEdit->toPlainText().simplified(); // 移除空格
                if (hexData.size() % 2 != 0) {
                    qDebug() << "Error: Incomplete hex data!";
                    return;
                }

                QByteArray byteArray;
                byteArray.resize(hexData.length() / 2);

                bool ok;
                for (int i = 0; i < hexData.length(); i += 2) {
                    QString byte = hexData.mid(i, 2);
                    byteArray[i / 2] = static_cast<char>(byte.toInt(&ok, 16));
                    if (!ok) {
                        qDebug() << "Error: Invalid hex data!";
                        return;
                    }
                }

                // 发送HEX格式的数据
                tcpSocket->write(byteArray);
            }
        } else { // ASCII format
            // 从发送区获取ASCII格式的数据并发送
            if (!ui->sendTextEdit->toPlainText().isEmpty()) {
                tcpSocket->write(ui->sendTextEdit->toPlainText().toUtf8());
            }
        }
    } else {
        qDebug() << "No client connected. Cannot send data.";
    }
}

void Server::displayReceivedData()
{
    QByteArray receivedData = tcpSocket->readAll();

    QString displayData;
    if (ui->receiveFormatComboBox->currentIndex() == 1) { // HEX format
        QString hexData;
        for (int i = 0; i < receivedData.size(); ++i) {
            hexData += QString("%1 ").arg(static_cast<unsigned char>(receivedData.at(i)), 2, 16, QChar('0')).toUpper();
        }
        displayData = hexData;
    } else { // ASCII format
        displayData = QString::fromUtf8(receivedData);
    }

    if (!ui->stopDisplayCheckBox->isChecked()) {
        appendToReceive(displayData);
    }
}

三、功能测试

以下分为三部分进行验证,主要测试均为客户端与服务器之间的ASCLL与HEX数据收发。

1、自制客户端与野火网络调试助手之间通信

输入服务器端口8000,启动服务器监听,点击客户端连接按钮后提示“Successfully connected to server!”并且禁用的控件显示为可用状态,表明自制客户端与服务器实现了连接。当客户端以HEX格式发送数据32 32 32时,服务器接收到ASCLL数据2 2 2。

2、自制服务器与野火网络调试助手之间通信

输入服务器端口8000,启动服务器监听,点击野火客户端连接按钮后服务器的Label提示状态转为“Sever running : Waiting for connection...”表明客户端与自制服务器实现了连接。当客户端以HEX格式发送数据32 32 32时,服务器接收到ASCLL数据2 2 2。

3、自制服务器与自制客户端之间通信

输入服务器端口8000,启动服务器监听,点击客户端连接按钮后客户端提示“Successfully connected to server!”并且禁用的控件显示为可用状态,服务器的Label控件提示状态转为“Sever running : Waiting for connection...”表明自制客户端与自制服务器实现了连接。当客户端以HEX格式发送数据32 32 32时,服务器接收到ASCLL数据2 2 2。

四、程序源码

client.h

#ifndef CLIENT_H
#define CLIENT_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QHostAddress>

QT_BEGIN_NAMESPACE
namespace Ui { class Client; }
QT_END_NAMESPACE

class Client : public QMainWindow
{
    Q_OBJECT

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

private slots:
    // 槽函数声明
    void connectToServer();
    void disconnectFromServer();
    void sendNewLine();
    void clearReceivedData();
    void toggleDisplay();
    void displayReceivedData();
    void formatChanged(int index);
    void updateSendOptions(bool connected);
    void updateRecvOptions(bool connected);
    void clearSend();
    QString getIp(); // 获取本机IP的函数

private:
    Ui::Client *ui;
    QTcpSocket *tcpSocket;
    bool isConnected;

    void initialize(); // 初始化函数,用于显示本地IP地址;
};

#endif // CLIENT_H

client.cpp

#include "client.h"
#include "ui_client.h"
#include <QMessageBox>
#include <QDebug>
#include <QNetworkInterface>
#include <QHostInfo>

Client::Client(QWidget *parent)
    : QMainWindow(parent),
      ui(new Ui::Client),
      tcpSocket(new QTcpSocket(this)),
      isConnected(false)
{
    ui->setupUi(this);

    // 设置默认状态
    updateSendOptions(false); // 更新发送选项状态为禁用
    updateRecvOptions(false); // 更新接收选项状态为禁用

    // 设置默认格式选项
    ui->sendFormatComboBox->setCurrentIndex(0); // 设置发送格式为 ASCII
    ui->receiveFormatComboBox->setCurrentIndex(0); // 设置接收格式为 ASCII

    // 连接按钮信号和槽
    connect(ui->connectButton, &QPushButton::clicked, this, &Client::connectToServer);
    connect(ui->disconnectButton, &QPushButton::clicked, this, &Client::disconnectFromServer);
    connect(ui->sendButton, &QPushButton::clicked, this, &Client::sendNewLine);
    connect(ui->clearRecvButton, &QPushButton::clicked, this, &Client::clearReceivedData);
    connect(ui->clearSendButton, &QPushButton::clicked, this, &Client::clearSend);
    connect(ui->stopDisplayCheckBox, &QCheckBox::toggled, this, &Client::toggleDisplay);
    connect(ui->receiveFormatComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Client::formatChanged);
    connect(tcpSocket, &QTcpSocket::readyRead, this, &Client::displayReceivedData);

    // 初始化窗口,显示本地 IP 地址
    initialize();
}

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

QString Client::getIp() {
    QString myipv4Address;

#ifdef _WIN32
    // Windows 系统下获取本地主机信息
    QHostInfo vHostInfo = QHostInfo::fromName(QHostInfo::localHostName());
    QList<QHostAddress> vAddressList = vHostInfo.addresses();
#else
    // 非 Windows 系统下获取所有网络接口信息
    QList<QHostAddress> vAddressList = QNetworkInterface::allAddresses();
#endif

    // 遍历地址列表以查找有效的 IPv4 地址
    for (int i = 0; i < vAddressList.size(); i++) {
        if (!vAddressList.at(i).isNull() &&
            vAddressList.at(i) != QHostAddress::LocalHost &&
            vAddressList.at(i).protocol() == QAbstractSocket::IPv4Protocol) {
            myipv4Address = vAddressList.at(i).toString();
            break;
        }
    }

    return myipv4Address;
}

void Client::initialize() {
    QString localIP = getIp();
    ui->ipLineEdit->setText(localIP);
}

void Client::connectToServer()
{
    if (!isConnected) {
        QString ipAddress = ui->ipLineEdit->text();
        quint16 port = ui->portLineEdit->text().toUShort();

        tcpSocket->connectToHost(QHostAddress(ipAddress), port);

        if (tcpSocket->waitForConnected(3000)) {
            QMessageBox::information(this, "Connected", "Successfully connected to server!");
            isConnected = true;
            updateSendOptions(true);
            updateRecvOptions(true);
            ui->sendTextEdit->setEnabled(true); // Enable send text box upon successful connection
        } else {
            QMessageBox::critical(this, "Error", "Connection failed!");
        }
    }
}

void Client::disconnectFromServer()
{
    if (isConnected) {
        tcpSocket->disconnectFromHost();
        isConnected = false;
        updateSendOptions(false);
        updateRecvOptions(false);
        ui->sendTextEdit->setEnabled(false); // Disable send text box upon disconnection
    }
}

void Client::sendNewLine()
{
    if (isConnected) {
        if (ui->sendFormatComboBox->currentIndex() == 1) { // HEX format
            if (!ui->sendTextEdit->toPlainText().isEmpty()) {
                QString hexData = ui->sendTextEdit->toPlainText().simplified(); // Remove spaces
                if (hexData.size() % 2 != 0) {
                    qDebug() << "Error: Incomplete hex data!";
                    return;
                }

                QByteArray byteArray;
                byteArray.resize(hexData.length() / 2);

                bool ok;
                for (int i = 0; i < hexData.length(); i += 2) {
                    QString byte = hexData.mid(i, 2);
                    byteArray[i / 2] = static_cast<char>(byte.toInt(&ok, 16));
                    if (!ok) {
                        qDebug() << "Error: Invalid hex data!";
                        return;
                    }
                }

                tcpSocket->write(byteArray);
            }
        } else { // ASCII format
            if (!ui->sendTextEdit->toPlainText().isEmpty()) {
                tcpSocket->write(ui->sendTextEdit->toPlainText().toUtf8());
            }
        }
    } else {
        qDebug() << "Not connected to a server. Cannot send data.";
    }
}

void Client::clearReceivedData()
{
    ui->recvTextEdit->clear();
}

void Client::toggleDisplay()
{
    if (ui->stopDisplayCheckBox->isChecked()) {
        ui->recvTextEdit->setReadOnly(true);
    } else {
        ui->recvTextEdit->setReadOnly(false);
    }
}

void Client::displayReceivedData()
{
    QByteArray receivedData = tcpSocket->readAll();

    QString displayData;
    if (ui->receiveFormatComboBox->currentIndex() == 1) { // HEX format
        QString hexData;
        for (int i = 0; i < receivedData.size(); ++i) {
            hexData += QString("%1 ").arg(static_cast<unsigned char>(receivedData.at(i)), 2, 16, QChar('0')).toUpper();
        }
        displayData = hexData;
    } else { // ASCII format
        displayData = QString::fromUtf8(receivedData);
    }

    if (!ui->stopDisplayCheckBox->isChecked()) {
        ui->recvTextEdit->append(displayData);
    }
}

void Client::formatChanged(int index)
{
    Q_UNUSED(index);
    displayReceivedData();
}

void Client::updateSendOptions(bool connected)
{
    ui->sendButton->setEnabled(connected);
    ui->sendTextEdit->setEnabled(connected);
    ui->clearSendButton->setEnabled(connected);
    ui->sendFormatComboBox->setEnabled(connected);
}

void Client::updateRecvOptions(bool connected)
{
    ui->clearRecvButton->setEnabled(connected);
    ui->stopDisplayCheckBox->setEnabled(connected);
    ui->receiveFormatComboBox->setEnabled(connected);
}

void Client::clearSend()
{
    ui->sendTextEdit->clear();
}

server.h

#ifndef SERVER_H
#define SERVER_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Server; }
QT_END_NAMESPACE

class Server : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_connectButton_clicked();
    void on_disconnectButton_clicked();
    void on_sendButton_clicked();
    void on_clearSendButton_clicked();
    void on_clearReceiveButton_clicked();
    void on_stopDisplayCheckBox_toggled(bool checked);
    void on_receiveFormatComboBox_currentIndexChanged(int index);

private:
    Ui::Server *ui;
    QTcpServer *tcpServer;
    QTcpSocket *tcpSocket;
    QString localIP;

    void displayLocalIP();
    void appendToReceive(const QString &message);
    void displayReceivedData();
};

#endif // SERVER_H

server.cpp

#include "server.h"
#include "ui_server.h"
#include <QMessageBox>
#include <QDebug>
#include <QNetworkInterface>

Server::Server(QWidget *parent)
    : QMainWindow(parent),
      ui(new Ui::Server),
      tcpServer(new QTcpServer(this)),
      tcpSocket(new QTcpSocket(this))
{
    ui->setupUi(this);

    // 显示本地IP地址
    displayLocalIP();

    // 监听连接请求
    connect(tcpServer, &QTcpServer::newConnection, this, [this]() {
        // 接收连接并分配socket
        tcpSocket = tcpServer->nextPendingConnection();
        // 当有数据到达时触发显示数据函数
        connect(tcpSocket, &QTcpSocket::readyRead, this, &Server::displayReceivedData);
    });
}

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

void Server::displayLocalIP()
{
    // 获取本地IP地址并在UI中显示
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    for (const QHostAddress &address : ipAddressesList) {
        if (address != QHostAddress::LocalHost && address.toIPv4Address()) {
            localIP = address.toString();
            ui->localIPLineEdit->setText(localIP);
            break;
        }
    }
}

void Server::appendToReceive(const QString &message)
{
    // 将接收到的信息追加到接收区
    if (!ui->stopDisplayCheckBox->isChecked()) {
        ui->receiveTextEdit->append(message);
    }
}

void Server::on_connectButton_clicked()
{
    // 启动服务器监听连接请求
    if (!tcpServer->isListening()) {
        quint16 port = ui->portLineEdit->text().toUShort();
        if (!tcpServer->listen(QHostAddress::Any, port)) {
            QMessageBox::critical(this, "Error", "Unable to start the server!");
            return;
        }
        ui->statusLabel->setText("Server running: Waiting for connection...");
    }
}

void Server::on_disconnectButton_clicked()
{
    // 停止服务器监听
    if (tcpServer->isListening()) {
        tcpServer->close();
        ui->statusLabel->setText("Server stopped.");
    }
}

void Server::on_sendButton_clicked()
{
    // 检查是否与客户端连接
    if (tcpSocket->state() == QAbstractSocket::ConnectedState) {
        // 检查发送数据的格式
        if (ui->sendFormatComboBox->currentIndex() == 1) { // HEX format
            // 从发送区获取HEX格式的数据并发送
            if (!ui->sendTextEdit->toPlainText().isEmpty()) {
                QString hexData = ui->sendTextEdit->toPlainText().simplified(); // 移除空格
                if (hexData.size() % 2 != 0) {
                    qDebug() << "Error: Incomplete hex data!";
                    return;
                }

                QByteArray byteArray;
                byteArray.resize(hexData.length() / 2);

                bool ok;
                for (int i = 0; i < hexData.length(); i += 2) {
                    QString byte = hexData.mid(i, 2);
                    byteArray[i / 2] = static_cast<char>(byte.toInt(&ok, 16));
                    if (!ok) {
                        qDebug() << "Error: Invalid hex data!";
                        return;
                    }
                }

                // 发送HEX格式的数据
                tcpSocket->write(byteArray);
            }
        } else { // ASCII format
            // 从发送区获取ASCII格式的数据并发送
            if (!ui->sendTextEdit->toPlainText().isEmpty()) {
                tcpSocket->write(ui->sendTextEdit->toPlainText().toUtf8());
            }
        }
    } else {
        qDebug() << "No client connected. Cannot send data.";
    }
}

void Server::on_clearSendButton_clicked()
{
    // 清空发送区
    ui->sendTextEdit->clear();
}

void Server::on_clearReceiveButton_clicked()
{
    // 清空接收区
    ui->receiveTextEdit->clear();
}

void Server::on_stopDisplayCheckBox_toggled(bool checked)
{
    // 控制是否显示接收到的数据
    Q_UNUSED(checked);
    displayReceivedData();
}

void Server::displayReceivedData()
{
    QByteArray receivedData = tcpSocket->readAll();

    QString displayData;
    if (ui->receiveFormatComboBox->currentIndex() == 1) { // HEX format
        QString hexData;
        for (int i = 0; i < receivedData.size(); ++i) {
            hexData += QString("%1 ").arg(static_cast<unsigned char>(receivedData.at(i)), 2, 16, QChar('0')).toUpper();
        }
        displayData = hexData;
    } else { // ASCII format
        displayData = QString::fromUtf8(receivedData);
    }

    if (!ui->stopDisplayCheckBox->isChecked()) {
        appendToReceive(displayData);
    }
}

void Server::on_receiveFormatComboBox_currentIndexChanged(int index)
{
    Q_UNUSED(index);
    // 处理接收数据的格式变化
    displayReceivedData();
}

五、工程文件

本人也是刚开始学习,里面可能存在一些不对的地方,欢迎留言讨论。

链接1为工程文件,链接2为获取本地IP的博客,链接3为封包的博客。

https://download.csdn.net/download/please_take/88691846
https://blog.csdn.net/weixin_34245082/article/details/92270355?spm=1001.2014.3001.5506
https://blog.csdn.net/F_Xiao_bai/article/details/130419561?spm=1001.2014.3001.5506

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值