侧边栏壁纸
  • 累计撰写 278 篇文章
  • 累计创建 3 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

【QT】TCP、UDP通信

xuanxuan
2021-03-23 / 0 评论 / 0 点赞 / 4 阅读 / 5503 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2024-02-14,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

UDP、TCP

UDP

  • UDP(User Datagram Protocol,用户数据报协议)

UDP是一个轻量级、不可靠、面向数据报的、无连接的协议,多用与可靠性不严格,不是非常重要的传输。

QUdpSocket类继承自QAbstractSocket,用来发送和接收UDP数据报。

“Socket”即套接字,即IP地址+端口号。其中IP地址指定了网络中的一台主机,端口号则指定了该主机上的一个网络程序,使用套接字即可实现网络上的两个应用程序之间的通信。

QUdpSocket支持IPv4广播,要广播数据报,则只需要发送到一个特殊的地址,QHostAddress::Broadcast(255.255.255.255),数据报一般建议发送字节数小于512字节。端口号选择1024~65535(1024一下的常用作保留端口号,如FTP常用端口号21,Telnet常用端口号23,DNS域名服务器常用端口号53等)。


示例:

发送端

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    m_sender = new QUdpSocket(this);

}

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

void Widget::on_pushButton_clicked()
{
    QByteArray dataGram = ui->lineEdit->text().toUtf8();
    m_sender->writeDatagram(dataGram.data(),
                                dataGram.size(),
                                QHostAddress::Broadcast,
                                6666);
}

接收端

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_receiver = new QUdpSocket(this);
    //绑定
    m_receiver->bind(6666,QUdpSocket::ShareAddress);
    //有数据来了,就处理。
    connect(m_receiver,&QUdpSocket::readyRead,this,&Widget::processData);
}

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

void Widget::processData()
{
   //有未处理的数据报
   while(m_receiver->hasPendingDatagrams()){

        QByteArray dataGram;

        dataGram.resize(m_receiver->pendingDatagramSize());

        m_receiver->readDatagram(dataGram.data(),dataGram.size());

        ui->label_2->setText(dataGram);
     }
}

image-20220323121512761


TCP

  • TCP(Transmission Control Protocol,传输控制协议)

多个网络协议包括HTTP和FTP都是基于TCP协议,TCP是面向数据流和连接的可靠的传输协议。

QTcpSocket继承自QAbstractSocket,与QUdpSocket传输的数据报不同的是,QTcpSocket传输的是连续的数据流,尤其适合连续的数据传输,TCP一般分为客户端和服务端,即C/S(Client/Server)模型。

QTcpSocket代表了两个独立的数据流,一个用来读取数据,一个用来写入数据,分别采用QTcpSocket::read()及QTcpSocket::write()操作,读取数据前先调用QTcpSocket::bytesAvaliable来确定已有足够的数据可用。

QTcpServer处理客户端的连接,可通过QTcpServer::listen()监听客户端发来的连接请求,每当有客户端连接时会发射newConnection()信号,QTcpSocket可用于读取客户端发来的数据报,亦可以发送数据报。

示例:

客户端

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

const int gTcpPort = 8888;

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_tcpSocket = new QTcpSocket(this);
    //收到数据开始处理
    connect(m_tcpSocket,&QTcpSocket::readyRead,
            this,&Widget::onReadMessage);

    connect(m_tcpSocket,SIGNAL(SocketError),
            this,SLOT(onDisplayError(QAbstractSocket::SocketError)));

    ui->hostLineEdit->setText("127.0.0.1");

    ui->portLineEdit->setText(QString::number(gTcpPort));
}

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

void Widget::onReadMessage(){
    QByteArray bt;

    bt.resize(m_tcpSocket->bytesAvailable());
    m_tcpSocket->read(bt.data(),bt.size());//读取到bt中

    ui->msgLabel->setText(bt);
}

void Widget::onDisplayError(QAbstractSocket::SocketError e){
    qDebug()<<"SocketError:"<<e<<endl
           <<m_tcpSocket->errorString();
}

void Widget::on_connectBtn_clicked()
{
    m_tcpSocket->abort();//终止
    //ip地址,端口
    m_tcpSocket->connectToHost(ui->hostLineEdit->text(),gTcpPort);//链接到主机

}

void Widget::on_sendBtn_clicked()
{
    m_tcpSocket->write(ui->sendLineEdit->text().toUtf8());
    m_tcpSocket->flush();//清空缓冲区
}

服务端

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    m_tcpServer = new QTcpServer(this);
    m_tcpSocket = new QTcpSocket(this);//保存链接进来的客户端

    //监听指定客户端发来的请求
    if(!m_tcpServer->listen(QHostAddress::Any,8888)){
        qDebug()<<m_tcpServer->errorString();
        close();
    }

    //有新的链接请求
    connect(m_tcpServer,&QTcpServer::newConnection,this,&Widget::onNewConnect);

    // 给链接的客户端反馈信息
    connect(m_tcpServer,&QTcpServer::newConnection,this,&Widget::onSendMessage);

}

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

void Widget::onNewConnect()
{

    m_tcpSocket = m_tcpServer->nextPendingConnection();//获取当前新来的链接

    //断开链接——销毁
    connect(m_tcpSocket,&QTcpSocket::disconnected,m_tcpServer,&QTcpSocket::deleteLater);

    //来消息后发送readyRead信号,与读取数据方法进行链接
    connect(m_tcpSocket,&QTcpSocket::readyRead,this,&Widget::onReadMessage);
}

void Widget::onSendMessage()
{
    QString str = "你好,client";
    m_tcpSocket->write(str.toUtf8());//写入socket
    ui->label->setText("发送数据成功!");

}

void Widget::onReadMessage()
{
    QByteArray bt = m_tcpSocket->readAll();
    ui->readLabel->setText(bt);
}

image-20220323215110060

0

评论区