Overview
UDP (User Datagram Protocol)
It is a simple transport layer protocol. Unlike TCP, UDP does not provide reliable data transmission and error detection mechanisms. UDP is mainly used for applications that have high real-time requirements and low data transmission reliability requirements, such as audio, video, real-time games, etc.
UDP
Use connectionless datagram transmission mode. Before transmitting data, the sender and receiver do not need to establish a persistent connection, they only need to send data messages. Each data message is independent and has no context, so there is no guarantee that it will be received in the order in which it was sent.
Features of the UDP protocol include:
- No connectivity: No connection is required to establish and maintain between the sender and receiver.
- Fastness: Due to the lack of connectivity, UDP transfer speed is relatively fast.
- No reliability guarantee: UDP does not provide reliable data transmission and does not guarantee the integrity and correctness of data.
- Simplicity: The UDP protocol header is shorter and takes up less data transmission.
UDP data transmission diagram:
QUdpSocket
QUdpSocket类
provides a UDP socket.
QUdpSocket
is a subclass of QAbstractSocket
that allows sending and receiving UDP datagrams.
Here socket
is the so-called socket. Simply put, it is an IP address + a Port number.
The most common way to use this class is to use bind()
to bind to an address and port, and then call writeDatagram()
and signal, the incoming datagram should be read, otherwise the signal will not be emitted for the next datagram. Note: When receiving the to read it. or returns true. Call pendingDatagramSize() to get the size of the first pending datagram, and call signal is emitted whenever a datagram arrives. In this case, A . signal each time it writes a datagram to the network. If you just want to send datagrams, you don't need to call A socket emits the . to transmit data. If you want to use the standard QIODevice functions read(), readLine(), write(), etc., you must first connect the socket directly to the peer by calling readDatagram()
/ receiveDatagram()
connectToHost()
bytesWritten()
bind()
readyRead()
hasPendingDatagrams()
readDatagram()
receiveDatagram()
readyRead()
QUdpSocket
supports IPv4 broadcast, which is a way of sending data in an IPv4 network to all hosts on the same network.
In an IPv4 network, the broadcast address is a special IP address used to indicate all hosts in the corresponding network.
IPv4 broadcast uses a specific IP address, that is, when all host bits of the network address are 1, the host address is 0. For example, in a network of 192.168.0.0/24, the broadcast address is 192.168.0.255.
Using IPv4 broadcast, data can be sent to all hosts on the same network at once instead of sending it to each host one by one. This is very useful in some applications, such as notifying all hosts in a LAN to perform a certain operation, or distributing IP addresses in the DHCP protocol, etc.
However, since data sent by IPv4 broadcasts will be received by all hosts on the same network, this may also cause some security and performance issues. Therefore, the use of broadcasts in IPv4 networks requires caution and appropriate restrictions and controls on broadcasts.
For example:
void Server::initSocket()
{
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::LocalHost, 7755);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(readPendingDatagrams()));
}
void Server::readPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QNetworkDatagram datagram = udpSocket->receiveDatagram();
processTheDatagram(datagram);
}
}
QUdpSocket
also supports UDP multicast. Use joinMulticastGroup()
and leaveMulticastGroup()
to control group membership, and QAbstractSocket::MulticastTtlOption
and QAbstractSocket::MulticastLoopbackOption
to set , you can also use connectToHost() to establish a virtual connection with the UDP server, and then use read() and write() to exchange datagrams without specifying each the receiver of the datagram. Using to query. to control the outbound interface of multicast datagrams, and use socket options. Use TTL
and loopback
setMulticastInterface()
multicastInterface()
QUdpSocket
Example
The following is a sender and a receiver. The sender sends data regularly and the receiver displays it.
sender.h
#include <QWidget>
QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QLabel;
class QPushButton;
class QTimer;
class QUdpSocket;
QT_END_NAMESPACE
class Sender : public QWidget
{
Q_OBJECT
public:
Sender(QWidget *parent = 0);
private slots:
void startBroadcasting();
void broadcastDatagram();
private:
QLabel *statusLabel;
QPushButton *startButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QUdpSocket *udpSocket;
QTimer *timer;
int messageNo;
};
sender.cpp
#include <QtWidgets>
#include <QtNetwork>
#include "sender.h"
Sender::Sender(QWidget *parent)
: QWidget(parent)
{
statusLabel = new QLabel(tr("绑定 端口 45454"));
statusLabel->setWordWrap(true);
startButton = new QPushButton(tr("&Start"));
quitButton = new QPushButton(tr("&Quit"));
buttonBox = new QDialogButtonBox;
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
timer = new QTimer(this);
udpSocket = new QUdpSocket(this);
messageNo = 1;
connect(startButton, SIGNAL(clicked()), this, SLOT(startBroadcasting()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(timer, SIGNAL(timeout()), this, SLOT(broadcastDatagram()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle(tr("广播发送"));
}
void Sender::startBroadcasting()
{
startButton->setEnabled(false);
timer->start(1000);
}
void Sender::broadcastDatagram()
{
statusLabel->setText(tr("现在 广播 信息 %1").arg(messageNo));
QByteArray datagram = "广播 信息 " + QByteArray::number(messageNo);
udpSocket->writeDatagram(datagram.data(), datagram.size(),
QHostAddress::Broadcast, 45454);
++messageNo;
}
receiver.h
#include <QWidget>
QT_BEGIN_NAMESPACE
class QLabel;
class QPushButton;
class QUdpSocket;
class QAction;
QT_END_NAMESPACE
class Receiver : public QWidget
{
Q_OBJECT
public:
Receiver(QWidget *parent = 0);
private slots:
void processPendingDatagrams();
private:
QLabel *statusLabel;
QPushButton *quitButton;
QUdpSocket *udpSocket;
};
receiver.cpp
#include <QtWidgets>
#include <QtNetwork>
#include "receiver.h"
Receiver::Receiver(QWidget *parent)
: QWidget(parent)
{
statusLabel = new QLabel(tr("监听 广播 信息"));
statusLabel->setWordWrap(true);
quitButton = new QPushButton(tr("&Quit"));
udpSocket = new QUdpSocket(this);
udpSocket->bind(45454, QUdpSocket::ShareAddress);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(processPendingDatagrams()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle(tr("广播 接收"));
}
void Receiver::processPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
statusLabel->setText(tr("接收 数据: \"%1\"")
.arg(datagram.data()));
}
}
Effect
The default display is as follows:
When clicking Send:
in conclusion
青春就像一只容器,装满了不安躁动青涩与偶尔的疯狂
。