【QT实现TCP和UDP协议通信(一)】

QT实现TCP和UDP协议通信(一)

编译环境 :MSVC 2010 32bit (本项目和编译环境无关)
语言 :C++
作者 :wddkxg
时间 :2022.04.24
项目 :Server(服务器端) + Client(客户端)

Server(服务器端)

1.创建新项目 选择Qt Widget Application即可 。

2.项目工程文件中(.pro)加入 QT += network,引入网络通信模块

3.引入头文件 , ,

4.ui界面设计 可以设计的相对简单 。

一个lineEdit 用于输入端口号,一个lineEdit 用于显示连接状态,两个RadioButton为选择协议,
一个PushButton 为侦听按钮 ,再加上一个TextEdit用于显示信息文本
Server的ui设计图

5.Server需要的几个功能:侦听端口、创建连接、读取数据(分为TCP和UDP协议)

对应的槽函数如下所示:
void on_pushButton_listen_clicked();//TCP侦听
void server_new_connect(); //创建新连接
void socket_read_data();//TCP读取缓冲区数据
void read_data();//UDP读取缓冲区数据

6.创建对象:

QUdpSocket *uServer;//UDP套接字对象
QTcpServer *mServer;
QTcpSocket *mSocket;//TCP套接字对象

7.源码:

server.h

#ifndef SERVER_H
#define SERVER_H

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


namespace Ui { class Server; }


class Server : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_pushButton_listen_clicked();//TCP侦听

    void server_new_connect(); //创建新连接

    void socket_read_data();//TCP读取缓冲区数据

    void read_data();//UDP读取缓冲区数据

    void on_comboBox_currentIndexChanged();//界面转换

private:
    Ui::Server *ui;
    QUdpSocket *uServer;//UDP套接字对象
    QTcpServer *mServer;
    QTcpSocket *mSocket;//TCP套接字对象
    int i1,i2;
    int j1,j2;
};
#endif // SERVER_H

server.cpp

/******************************************************************************************/
/*                                        服务端                                          */
/*                                        2022.03.02                                      */
/*                                        wddkxg                                          */
/*                                        v1.0                                            */
/******************************************************************************************/

#include "server.h"
#include "ui_server.h"

/*构造函数*/
Server::Server(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::Server)
{
    ui->setupUi(this);
    ui->portEdit->setText("8080");//默认端口号为8080

    mServer = new QTcpServer();//初始化TCP对象
    connect(mServer,&QTcpServer::newConnection,this,&Server::server_new_connect);
    //初始化表格行列计数变量
    i1 = 0;
    j1 = 0;
    i2 = 0;
    j2 = 0;

    uServer = new QUdpSocket(this); //初始化UDP对象
    uServer->bind(QHostAddress("10.0.0.58"),8080);//绑定ip地址和端口号
    connect(uServer,SIGNAL(readyRead()),this,SLOT(read_data()));//连接信号槽
}

/*UDP读取缓冲数据*/
void Server::read_data()
{
    if(ui->radioButton_UDP->isChecked())//判断是否勾选UDP协议
    {
        qDebug()<<"recv_UDP";

        QByteArray arr;//创建QByteArray对象存储缓冲区数据
        arr.resize(uServer->bytesAvailable());//设置字符串大小
        uServer->readDatagram(arr.data(),arr.size());//读取缓冲区数据
        qDebug()<<uServer->readDatagram(arr.data(),arr.size());

        QString str ;//创建QString对象用于进行缓冲数据的处理
        str.prepend(arr);//QByteArray转QString
        qDebug()<<"str="<<str;

        if(ui->comboBox->currentText() == "DataA")//处理为DataA数据类型
        {
            ui->stackedWidget->setCurrentIndex(0);
            qDebug()<<str.section(' ',0,0);
            ui->table_output_A->item(i2,j2)->setText(str.section(' ',0,j2));
            j2++;
            qDebug()<<str.section(' ',1,1);
            ui->table_output_A->item(i2,j2)->setText(str.section(' ',1,j2));
            j2++;
            qDebug()<<str.section(' ',2,2);
            ui->table_output_A->item(i2,j2)->setText(str.section(' ',2,j2));

            i2++;
            j2=0;

        }
        else//处理为DataB数据类型
        {
            ui->stackedWidget->setCurrentIndex(1);
            ui->table_output_B->item(i2,j2++)->setText(str.section(' ',0,0));
            ui->table_output_B->item(i2,j2++)->setText(str.section(' ',1,1));
            i2++;
            j2=0;
        }
    }

}


/*析构函数*/
Server::~Server()
{
    uServer->close();
    uServer->deleteLater();
    mServer->close();
    mServer->deleteLater();
    delete ui;
}
/*TCP侦听*/
void Server::on_pushButton_listen_clicked()
{
    if(ui->pushButton_listen->text() == QString::fromLocal8Bit("侦听"))
    {
        int port = ui->portEdit->text().toInt();
        if(!mServer->listen(QHostAddress("10.0.0.58"),port))//判断侦听本机端口和地址是否成功
        {
            ui->portEdit_state->setText(QString::fromLocal8Bit("侦听失败!"));//侦听失败
            qDebug()<<mServer->errorString();
            return;
        }
        ui->pushButton_listen->setText(QString::fromLocal8Bit("取消侦听"));//改变按键功能
        ui->portEdit_state->setText(QString::fromLocal8Bit("侦听成功!"));//侦听成功
        qDebug()<<"Listen successful!";
    }
    else//侦听失败
    {
        mSocket->abort();//销毁TCP套接字对象
        mServer->close();
        ui->portEdit_state->setText(QString::fromLocal8Bit("侦听失败!"));//返回侦听失败
        ui->pushButton_listen->setText(QString::fromLocal8Bit("侦听"));//改变按键功能

    }
}

/*连接新用户*/
void Server::server_new_connect()
{
    mSocket = mServer->nextPendingConnection();
    QObject::connect(mSocket,&QTcpSocket::readyRead,this,&Server::socket_read_data);//连接函数槽
    ui->portEdit_state->setText(QString::fromLocal8Bit("连接成功!"));
//    ui->table_output_A->clear();
//    ui->table_output_B->clear();
    qDebug()<<"A client connect!";
}

/*接收数据*/
void Server::socket_read_data()
{
    if(ui->radioButton_TCP->isChecked())
    {
        QString str= mSocket->readAll();
        qDebug()<<"recv_TCP";
        if(ui->comboBox->currentText() == "DataA")//判断下拉选项的数据类型
        {
            ui->stackedWidget->setCurrentIndex(0);//切换为dataA数据格式表
            ui->table_output_A->item(i1,j1++)->setText(str.section(' ',0,0));
            ui->table_output_A->item(i1,j1++)->setText(str.section(' ',1,1));
            ui->table_output_A->item(i1,j1++)->setText(str.section(' ',2,2));
            i1++;
            j1=0;
        }
        else
        {
            ui->stackedWidget->setCurrentIndex(1);//切换为data数据格式表
            ui->table_output_B->item(i1,j1++)->setText(str.section(' ',0,0));
            ui->table_output_B->item(i1,j1++)->setText(str.section(' ',1,1));
            i1++;
            j1=0;
        }
    }

}
/*下拉框实现dataA与dataB数据结构表的切换*/
void Server::on_comboBox_currentIndexChanged()
{
    if(ui->comboBox->currentText() == "DataA")//判断选定数据类型
        ui->stackedWidget->setCurrentIndex(0);
    else
        ui->stackedWidget->setCurrentIndex(1);
}



main2.cpp

#include "server.h"
#include <QApplication>
#include <QTimer>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Server w;
    w.show();

    return a.exec();
}

8.以上为服务器端设计方案。下期会讲解客户端的设计方案 :)

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Qt实现TCPUDP双线程,可以使用QtQTcpSocket和QUdpSocket类来实现。 首先,在服务器端,你可以创建一个QTcpServer对象来监听和接受TCP连接,并在每个新的连接上创建一个QTcpSocket对象来处理通信。同时,你也可以创建一个QUdpSocket对象来处理UDP通信。 以下是一个简单的示例代码,展示了如何在服务器端使用TCPUDP双线程: ```cpp // server.h #ifndef SERVER_H #define SERVER_H #include <QMainWindow> #include <QTcpServer> #include <QTcpSocket> #include <QUdpSocket> namespace Ui { class Server; } class Server : public QMainWindow { Q_OBJECT public: Server(QWidget *parent = nullptr); ~Server(); private slots: void on_pushButton_listen_clicked(); // TCP侦听 void server_new_connect(); // 创建新连接 void socket_read_data(); // TCP读取缓冲区数据 void read_data(); // UDP读取缓冲区数据 void on_comboBox_currentIndexChanged(); // 界面转换 private: Ui::Server *ui; QUdpSocket *uServer; // UDP套接字对象 QTcpServer *mServer; QTcpSocket *mSocket; // TCP套接字对象 int i1, i2; int j1, j2; }; #endif // SERVER_H ``` ```cpp // server.cpp #include "server.h" #include <QApplication> #include <QTimer> Server::Server(QWidget *parent) : QMainWindow(parent) , ui(new Ui::Server) { ui->setupUi(this); // 创建QTcpServer对象 mServer = new QTcpServer(this); // 连接新的连接信号和槽函数 connect(mServer, &QTcpServer::newConnection, this, &Server::server_new_connect); // 创建QUdpSocket对象 uServer = new QUdpSocket(this); // 连接readyRead信号和槽函数 connect(uServer, &QUdpSocket::readyRead, this, &Server::read_data); } Server::~Server() { delete ui; } void Server::on_pushButton_listen_clicked() { // 开始监听指定的端口 if (mServer->listen(QHostAddress::Any, ui->lineEdit_port->text().toInt())) { ui->textEdit_info->append("Server is listening..."); } else { ui->textEdit_info->append("Failed to start server!"); } } void Server::server_new_connect() { // 获取新的连接 mSocket = mServer->nextPendingConnection(); // 连接readyRead信号和槽函数 connect(mSocket, &QTcpSocket::readyRead, this, &Server::socket_read_data); // 输出连接信息 ui->textEdit_info->append("New client connected!"); } void Server::socket_read_data() { // 读取缓冲区数据 QByteArray data = mSocket->readAll(); // 处理数据 // ... } void Server::read_data() { // 读取缓冲区数据 QByteArray data = uServer->readAll(); // 处理数据 // ... } void Server::on_comboBox_currentIndexChanged() { // 界面转换 // ... } ``` 在上述示例中,`Server`类继承自`QMainWindow`,在构造函数中创建了`QTcpServer`和`QUdpSocket`对象,并连接了相应的信号和槽函数。其中,`on_pushButton_listen_clicked`槽函数用于开始监听指定的端口,`server_new_connect`槽函数用于处理新的TCP连接,`socket_read_data`槽函数用于读取TCP缓冲区数据,`read_data`槽函数用于读取UDP缓冲区数据,`on_comboBox_currentIndexChanged`槽函数用于界面转换。 请注意,以上代码只是一个简单示例,你可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葛狂的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值