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

这篇具有很好参考价值的文章主要介绍了Qt实践:TCP服务器和客户端的设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Qt:5.12.2

Qt Creator:4.11.1

通信方式:TCP\IP

语言:C++

一、TCP Client的设计

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

自动获取本地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的设计

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

Qt实践:TCP服务器和客户端的设计,qt,tcp/ip,服务器

获取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。

Qt实践:TCP服务器和客户端的设计,qt,tcp/ip,服务器

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

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

Qt实践:TCP服务器和客户端的设计,qt,tcp/ip,服务器

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

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

四、程序源码

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文章来源地址https://www.toymoban.com/news/detail-770682.html

到了这里,关于Qt实践:TCP服务器和客户端的设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 流媒体服务器SRS的搭建及QT下RTMP推流客户端的编写

        目前市面上有很多开源的流媒体服务器解决方案,常见的有SRS、EasyDarwin、ZLMediaKit和Monibuca。这几种的对比如下: (本图来源:https://www.ngui.cc/zz/1781086.html?action=onClick)     SRS(Simple Real-time Server)是一个开源的流媒体服务器,它支持RTMP、HLS、HTTP-FLV等多种流媒体协议

    2024年02月11日
    浏览(48)
  • Qt 服务器 获取发送客户端的QTcpSocket对象 和 该socket的ip和端口号

    遇到问题:         众多客户端发送过来请求数据,如何找到该客户端的 QTcpsocket对象给该对象回复消息? 解决办法:         QTcpSocket *ptr =   dynamic_castQTcpSocket *(sender());         解释:通过 dynamic_cast强行转换。QTcpSocket *类型的对象、谁发送了信号就会触发      

    2024年02月12日
    浏览(42)
  • QT实现tcp服务器客户端

    2024年02月07日
    浏览(59)
  • Qt 服务器/客户端TCP通讯

    最近需要用到TCP/IP通讯,这边就先找个简单的例程学习一下。Qt的TCP通讯编程可以使用QtNetwork模块,QtNetwork模块提供的类能够创建基于TCP/IP的客户端与服务端应用程序,一般会使用QTcpSocket、QTcpServer类 网络通信方式主要有两种:TCP与UDP。以下拷贝网络上总结两者之间的区别:

    2023年04月26日
    浏览(70)
  • TCP客户端及服务器端开发实践

    ① TCP客户端应用程序开发 ② TCP服务器端应用程序开发 客户端程序是指运行在用户设备上的程序,服务端程序是指运行在服务器设备上的程序,专门为客户端提供数据服务。那如何记忆呢? 主动发起建立连接请求的是客户端程序,等待接受连接请求的是服务端程序。 开发流

    2024年04月09日
    浏览(56)
  • QT实现TCP通信(服务器与客户端搭建)

    创建一个QTcpServer类对象,该类对象就是一个服务器 调用listen函数将该对象设置为被动监听状态,监听时,可以监听指定的ip地址,也可以监听所有主机地址,可以通过指定端口号,也可以让服务器自动选择 当有客户端发来连接请求时,该服务器会自动发射一个newConnection信号

    2024年02月09日
    浏览(56)
  • Qt多线程TCP服务器客户端传输文件

    TCP是面向连接的运输层协议。应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的(一对一)。 TCP提供可靠交付的服务。通过TCP 连接传送的数据,无差错、不丢失、不

    2024年02月13日
    浏览(55)
  • QT下的多线程TCP客户端和服务器

    qt下的QTcpSocket在同一个线程使用时没有问题的,但是如果进行跨线程,很容易出现问题。那么有什么方法可以跨线程进行使用吗? 答案是肯定的:使用QThread的movetothread可以完成扩线程接收。 首先是基于QTcpSocket的类 头文件tcpsocket.h 然后是cpp文件tcpsocket.cpp 再次基础上,创建

    2024年01月17日
    浏览(51)
  • 基于STM32F103,利用W5500芯片实现TCP客户端连接TCP服务器的实践

    尊敬的读者,您好!在这篇文章中,我们将一起深入了解如何使用STM32F103和W5500芯片,实现TCP客户端连接到TCP服务器的过程。在详细的步骤中,我们不仅会给出相关的理论介绍,同时也会提供实战代码以供大家参考和学习。希望大家在阅读完这篇文章后,能够有所收获。 实战

    2024年02月11日
    浏览(38)
  • UDP服务器和客户端的创建步骤

    一、创建用户数据报套接字(socket函数): 通信域选择 IPV4网络协议 、套接字类型选择 数据报式 ; 二、填充服务器的网络信息结构体: 1.定义网络信息结构体变量; 2.求出结构体变量的内存空间大小; 3.结构体清零; 4.使用IPV4网络协议; 5.预留给在终端输入的网络字节序

    2024年01月19日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包