一、概述
UDP即用户数据报协议(User Datagram Protocol),为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。
当谈到UDP协议时,为了与TCP协议比较,总是会谈到UDP的“不可靠性”。所谓的“不可靠”是指UDP通信双方在数据交换之前无需建立连接,发送方只管将数据发出,至于对方收没收到、数据丢没丢包就不在它的负责范围之内了。而TCP是面向连接的,可靠的通信协议,它的丢包重传机制确保了它的可靠性。至于二者的区别,概括起来就是TCP追求数据传输的可靠性,UDP追求数据传输的效率,因此在很多对实时性要求较高,而可靠性要求不是很高的场景下,如实时视频、语音传输服务中,普遍采用UDP协议。
二、Qt下的UDP通信流程
与TCP通信相比,Qt下的UDP要简单得多。UDP可以实现一对一,一对多,多对多的交互通信,它的每一个应用程序端都是数据收、发二合一的,因此也没有服务器和客户端之分。
- Qt项目中,首先在Pro文件中添加
network
模块:
包含UDP头文件QT += network
<QUdpSocket>
,并创建通信套接字对象udpSocket
- 绑定IP地址和端口号
udpSocket->bind(QHostAddress::Any,8888);
- 当接收到数据时,会触发
readyRead()
信号,绑定数据读取槽函数
其中,四个参数分别为数据、数据大小、IP地址、端口号,返回一个实际读取到的字节数,如果返回值为-1则表明读取失败;qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address = Q_NULLPTR, quint16 *port = Q_NULLPTR)
- 发送数据
qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
三、项目代码
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QUdpSocket>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void RcvData();
void on_pushButton_send_clicked();
void on_pushButton_close_clicked();
private:
Ui::Widget *ui;
QUdpSocket *udpSocket;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QHostAddress>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::Any,8888); //这个绑定其实是设置自己的端口号
connect(udpSocket,SIGNAL(readyRead()),this,SLOT(RcvData()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::RcvData()
{
char buf[1024] = {0};
QHostAddress address ;
quint16 port;
quint64 len = udpSocket->readDatagram(buf,sizeof(buf),&address,&port);
if(len>0)
{
QString str = QString("[%1:%2]:%3").arg(address.toString()).arg(port).arg(buf);
ui->textEdit_rcv->append(str);
}
}
void Widget::on_pushButton_send_clicked()
{
QHostAddress ip = (QHostAddress)ui->lineEdit_ip->text();
quint16 port = ui->lineEdit_port->text().toInt();
QString str = ui->textEdit_send->toPlainText();
udpSocket->writeDatagram(str.toUtf8().data(),ip,port);
ui->textEdit_rcv->append(str);
}
void Widget::on_pushButton_close_clicked()
{
this->close();
}