Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qudpsocket.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// Copyright (C) 2016 Intel Corporation.
3
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
// Qt-Security score:significant reason:default
5
6
//#define QUDPSOCKET_DEBUG
7
8
/*! \class QUdpSocket
9
10
\reentrant
11
\brief The QUdpSocket class provides a UDP socket.
12
13
\ingroup network
14
\inmodule QtNetwork
15
16
UDP (User Datagram Protocol) is a lightweight, unreliable,
17
datagram-oriented, connectionless protocol. It can be used when
18
reliability isn't important. QUdpSocket is a subclass of
19
QAbstractSocket that allows you to send and receive UDP
20
datagrams.
21
22
The most common way to use this class is to bind to an address and port
23
using bind(), then call writeDatagram() and readDatagram() /
24
receiveDatagram() to transfer data. If you want to use the standard
25
QIODevice functions read(), readLine(), write(), etc., you must first
26
connect the socket directly to a peer by calling connectToHost().
27
28
The socket emits the bytesWritten() signal every time a datagram
29
is written to the network. If you just want to send datagrams,
30
you don't need to call bind().
31
32
The readyRead() signal is emitted whenever datagrams arrive. In
33
that case, hasPendingDatagrams() returns \c true. Call
34
pendingDatagramSize() to obtain the size of the first pending
35
datagram, and readDatagram() or receiveDatagram() to read it.
36
37
\note An incoming datagram should be read when you receive the readyRead()
38
signal, otherwise this signal will not be emitted for the next datagram.
39
40
Example:
41
42
\snippet code/src_network_socket_qudpsocket.cpp 0
43
44
QUdpSocket also supports UDP multicast. Use joinMulticastGroup() and
45
leaveMulticastGroup() to control group membership, and
46
QAbstractSocket::MulticastTtlOption and
47
QAbstractSocket::MulticastLoopbackOption to set the TTL and loopback socket
48
options. Use setMulticastInterface() to control the outgoing interface for
49
multicast datagrams, and multicastInterface() to query it.
50
51
With QUdpSocket, you can also establish a virtual connection to a
52
UDP server using connectToHost() and then use read() and write()
53
to exchange datagrams without specifying the receiver for each
54
datagram.
55
56
The \l{broadcastsender}{Broadcast Sender},
57
\l{broadcastreceiver}{Broadcast Receiver},
58
\l{multicastsender}{Multicast Sender}, and
59
\l{multicastreceiver}{Multicast Receiver} examples illustrate how
60
to use QUdpSocket in applications.
61
62
\sa QTcpSocket, QNetworkDatagram
63
*/
64
65
#
include
"qudpsocket.h"
66
#
include
"qhostaddress.h"
67
#
include
"qnetworkdatagram.h"
68
#
include
"qnetworkinterface.h"
69
#
include
"qabstractsocket_p.h"
70
#
include
"qabstractsocketengine_p.h"
71
72
QT_BEGIN_NAMESPACE
73
74
#
ifndef
QT_NO_UDPSOCKET
75
76
#
define
QT_CHECK_BOUND
(
function
,
a
)
do
{
77
if
(
!
isValid
(
)
)
{
78
qWarning
(
function
" called on a QUdpSocket when not in QUdpSocket::BoundState"
)
;
79
return
(
a
)
;
80
}
}
while
(
0
)
81
82
class
QUdpSocketPrivate :
public
QAbstractSocketPrivate
83
{
84
Q_DECLARE_PUBLIC(QUdpSocket)
85
86
bool
doEnsureInitialized(
const
QHostAddress &bindAddress, quint16 bindPort,
87
const
QHostAddress &remoteAddress);
88
public
:
89
inline
bool
ensureInitialized(
const
QHostAddress &bindAddress, quint16 bindPort)
90
{
return
doEnsureInitialized(bindAddress, bindPort, QHostAddress()); }
91
92
inline
bool
ensureInitialized(
const
QHostAddress &remoteAddress)
93
{
return
doEnsureInitialized(QHostAddress(), 0, remoteAddress); }
94
};
95
96
bool
QUdpSocketPrivate::doEnsureInitialized(
const
QHostAddress &bindAddress, quint16 bindPort,
97
const
QHostAddress &remoteAddress)
98
{
99
const
QHostAddress *address = &bindAddress;
100
QAbstractSocket::NetworkLayerProtocol proto = address->protocol();
101
if
(proto == QUdpSocket::UnknownNetworkLayerProtocol) {
102
address = &remoteAddress;
103
proto = address->protocol();
104
}
105
106
// now check if the socket engine is initialized and to the right type
107
if
(!socketEngine || !socketEngine->isValid()) {
108
resolveProxy(remoteAddress.toString(), bindPort);
109
if
(!initSocketLayer(address->protocol()))
110
return
false
;
111
}
112
113
return
true
;
114
}
115
116
/*!
117
Creates a QUdpSocket object.
118
119
\a parent is passed to the QObject constructor.
120
121
\sa socketType()
122
*/
123
QUdpSocket::QUdpSocket(QObject *parent)
124
: QAbstractSocket(UdpSocket, *
new
QUdpSocketPrivate, parent)
125
{
126
d_func()->isBuffered =
false
;
127
}
128
129
/*!
130
Destroys the socket, closing the connection if necessary.
131
132
\sa close()
133
*/
134
QUdpSocket::~QUdpSocket()
135
{
136
}
137
138
#
ifndef
QT_NO_NETWORKINTERFACE
139
140
/*!
141
\since 4.8
142
143
Joins the multicast group specified by \a groupAddress on the default
144
interface chosen by the operating system. The socket must be in BoundState,
145
otherwise an error occurs.
146
147
Note that if you are attempting to join an IPv4 group, your socket must not
148
be bound using IPv6 (or in dual mode, using QHostAddress::Any). You must use
149
QHostAddress::AnyIPv4 instead.
150
151
This function returns \c true if successful; otherwise it returns \c false
152
and sets the socket error accordingly.
153
154
\note Joining IPv6 multicast groups without an interface selection is not
155
supported in all operating systems. Consider using the overload where the
156
interface is specified.
157
158
\sa leaveMulticastGroup()
159
*/
160
bool
QUdpSocket::joinMulticastGroup(
const
QHostAddress &groupAddress)
161
{
162
return
joinMulticastGroup(groupAddress, QNetworkInterface());
163
}
164
165
/*!
166
\since 4.8
167
\overload
168
169
Joins the multicast group address \a groupAddress on the interface \a
170
iface.
171
172
\sa leaveMulticastGroup()
173
*/
174
bool
QUdpSocket::joinMulticastGroup(
const
QHostAddress &groupAddress,
175
const
QNetworkInterface &iface)
176
{
177
Q_D(QUdpSocket);
178
QT_CHECK_BOUND
(
"QUdpSocket::joinMulticastGroup()"
,
false
);
179
return
d->socketEngine->joinMulticastGroup(groupAddress, iface);
180
}
181
182
/*!
183
\since 4.8
184
185
Leaves the multicast group specified by \a groupAddress on the default
186
interface chosen by the operating system. The socket must be in BoundState,
187
otherwise an error occurs.
188
189
This function returns \c true if successful; otherwise it returns \c false and
190
sets the socket error accordingly.
191
192
\note This function should be called with the same arguments as were passed
193
to joinMulticastGroup().
194
195
\sa joinMulticastGroup()
196
*/
197
bool
QUdpSocket::leaveMulticastGroup(
const
QHostAddress &groupAddress)
198
{
199
return
leaveMulticastGroup(groupAddress, QNetworkInterface());
200
}
201
202
/*!
203
\since 4.8
204
\overload
205
206
Leaves the multicast group specified by \a groupAddress on the interface \a
207
iface.
208
209
\note This function should be called with the same arguments as were passed
210
to joinMulticastGroup().
211
212
\sa joinMulticastGroup()
213
*/
214
bool
QUdpSocket::leaveMulticastGroup(
const
QHostAddress &groupAddress,
215
const
QNetworkInterface &iface)
216
{
217
QT_CHECK_BOUND
(
"QUdpSocket::leaveMulticastGroup()"
,
false
);
218
return
d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
219
}
220
221
/*!
222
\since 4.8
223
224
Returns the interface for the outgoing interface for multicast datagrams.
225
This corresponds to the IP_MULTICAST_IF socket option for IPv4 sockets and
226
the IPV6_MULTICAST_IF socket option for IPv6 sockets. If no interface has
227
been previously set, this function returns an invalid QNetworkInterface.
228
The socket must be in BoundState, otherwise an invalid QNetworkInterface is
229
returned.
230
231
\sa setMulticastInterface()
232
*/
233
QNetworkInterface QUdpSocket::multicastInterface()
const
234
{
235
Q_D(
const
QUdpSocket);
236
QT_CHECK_BOUND
(
"QUdpSocket::multicastInterface()"
, QNetworkInterface());
237
return
d->socketEngine->multicastInterface();
238
}
239
240
/*!
241
\since 4.8
242
243
Sets the outgoing interface for multicast datagrams to the interface \a
244
iface. This corresponds to the IP_MULTICAST_IF socket option for IPv4
245
sockets and the IPV6_MULTICAST_IF socket option for IPv6 sockets. The
246
socket must be in BoundState, otherwise this function does nothing.
247
248
\sa multicastInterface(), joinMulticastGroup(), leaveMulticastGroup()
249
*/
250
void
QUdpSocket::setMulticastInterface(
const
QNetworkInterface &iface)
251
{
252
Q_D(QUdpSocket);
253
if
(!isValid()) {
254
qWarning(
"QUdpSocket::setMulticastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState"
);
255
return
;
256
}
257
d->socketEngine->setMulticastInterface(iface);
258
}
259
260
#
endif
// QT_NO_NETWORKINTERFACE
261
262
/*!
263
Returns \c true if at least one datagram is waiting to be read;
264
otherwise returns \c false.
265
266
\sa pendingDatagramSize(), readDatagram()
267
*/
268
bool
QUdpSocket::hasPendingDatagrams()
const
269
{
270
QT_CHECK_BOUND
(
"QUdpSocket::hasPendingDatagrams()"
,
false
);
271
return
d_func()->socketEngine->hasPendingDatagrams();
272
}
273
274
/*!
275
Returns the size of the first pending UDP datagram. If there is
276
no datagram available, this function returns -1.
277
278
\sa hasPendingDatagrams(), readDatagram()
279
*/
280
qint64 QUdpSocket::pendingDatagramSize()
const
281
{
282
QT_CHECK_BOUND
(
"QUdpSocket::pendingDatagramSize()"
, -1);
283
return
d_func()->socketEngine->pendingDatagramSize();
284
}
285
286
/*!
287
Sends the datagram at \a data of size \a size to the host
288
address \a address at port \a port. Returns the number of
289
bytes sent on success; otherwise returns -1.
290
291
Datagrams are always written as one block. The maximum size of a
292
datagram is highly platform-dependent, but can be as low as 8192
293
bytes. If the datagram is too large, this function will return -1
294
and error() will return DatagramTooLargeError.
295
296
Sending datagrams larger than 512 bytes is in general disadvised,
297
as even if they are sent successfully, they are likely to be
298
fragmented by the IP layer before arriving at their final
299
destination.
300
301
\warning Calling this function on a connected UDP socket may
302
result in an error and no packet being sent. If you are using a
303
connected socket, use write() to send datagrams.
304
305
\sa readDatagram(), write()
306
*/
307
qint64 QUdpSocket::writeDatagram(
const
char
*data, qint64 size,
const
QHostAddress &address,
308
quint16 port)
309
{
310
Q_D(QUdpSocket);
311
#
if
defined
QUDPSOCKET_DEBUG
312
qDebug(
"QUdpSocket::writeDatagram(%p, %llu, \"%s\", %i)"
, data, size,
313
address.toString().toLatin1().constData(), port);
314
#
endif
315
if
(!d->doEnsureInitialized(QHostAddress::Any, 0, address))
316
return
-1;
317
if
(state() == UnconnectedState)
318
bind();
319
320
qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port));
321
d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
322
323
if
(sent >= 0) {
324
emit bytesWritten(sent);
325
}
else
{
326
if
(sent == -2) {
327
// Socket engine reports EAGAIN. Treat as a temporary error.
328
d->setErrorAndEmit(QAbstractSocket::TemporaryError,
329
tr(
"Unable to send a datagram"
));
330
return
-1;
331
}
332
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
333
}
334
return
sent;
335
}
336
337
/*!
338
\fn qint64 QUdpSocket::writeDatagram(const QByteArray &datagram,
339
const QHostAddress &host, quint16 port)
340
\overload
341
342
Sends the datagram \a datagram to the host address \a host and at
343
port \a port.
344
345
The function returns the number of bytes sent if it succeeded or -1 if it
346
encountered an error.
347
*/
348
349
/*!
350
\since 5.8
351
\overload
352
353
Sends the datagram \a datagram to the host address and port numbers
354
contained in \a datagram, using the network interface and hop count limits
355
also set there. If the destination address and port numbers are unset, this
356
function will send to the address that was passed to connectToHost().
357
358
If the destination address is IPv6 with a non-empty
359
\l{QHostAddress::scopeId()}{scope id} but differs from the interface index
360
in \a datagram, it is undefined which interface the operating system will
361
choose to send on.
362
363
The function returns the number of bytes sent if it succeeded or -1 if it
364
encountered an error.
365
366
\warning Calling this function on a connected UDP socket may
367
result in an error and no packet being sent. If you are using a
368
connected socket, use write() to send datagrams.
369
370
\sa QNetworkDatagram::setDestination(), QNetworkDatagram::setHopLimit(), QNetworkDatagram::setInterfaceIndex()
371
*/
372
qint64 QUdpSocket::writeDatagram(
const
QNetworkDatagram &datagram)
373
{
374
Q_D(QUdpSocket);
375
#
if
defined
QUDPSOCKET_DEBUG
376
qDebug(
"QUdpSocket::writeDatagram(%p, %i, \"%s\", %i)"
,
377
datagram.d->data.constData(),
378
datagram.d->data.size(),
379
datagram.destinationAddress().toString().toLatin1().constData(),
380
datagram.destinationPort());
381
#
endif
382
if
(!d->doEnsureInitialized(QHostAddress::Any, 0, datagram.destinationAddress()))
383
return
-1;
384
if
(state() == UnconnectedState)
385
bind();
386
387
qint64 sent = d->socketEngine->writeDatagram(datagram.d->data.constData(),
388
datagram.d->data.size(),
389
datagram.d->header);
390
d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
391
392
if
(sent >= 0) {
393
emit bytesWritten(sent);
394
}
else
{
395
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
396
}
397
return
sent;
398
}
399
400
/*!
401
\since 5.8
402
403
Receives a datagram no larger than \a maxSize bytes and returns it in the
404
QNetworkDatagram object, along with the sender's host address and port. If
405
possible, this function will also try to determine the datagram's
406
destination address, port, and the number of hop counts at reception time.
407
408
On failure, returns a QNetworkDatagram that reports \l
409
{QNetworkDatagram::isValid()}{not valid}.
410
411
If \a maxSize is too small, the rest of the datagram will be lost. If \a
412
maxSize is 0, the datagram will be discarded. If \a maxSize is -1 (the
413
default), this function will attempt to read the entire datagram.
414
415
\sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
416
*/
417
QNetworkDatagram QUdpSocket::receiveDatagram(qint64 maxSize)
418
{
419
Q_D(QUdpSocket);
420
421
#
if
defined
QUDPSOCKET_DEBUG
422
qDebug(
"QUdpSocket::receiveDatagram(%lld)"
, maxSize);
423
#
endif
424
QT_CHECK_BOUND
(
"QUdpSocket::receiveDatagram()"
, QNetworkDatagram());
425
426
if
(maxSize < 0)
427
maxSize = d->socketEngine->pendingDatagramSize();
428
if
(maxSize < 0)
429
return
QNetworkDatagram();
430
431
QNetworkDatagram result(QByteArray(maxSize, Qt::Uninitialized));
432
qint64 readBytes = d->socketEngine->readDatagram(result.d->data.data(), maxSize, &result.d->header,
433
QAbstractSocketEngine::WantAll);
434
d->hasPendingData =
false
;
435
d->hasPendingDatagram =
false
;
436
d->socketEngine->setReadNotificationEnabled(
true
);
437
if
(readBytes < 0) {
438
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
439
readBytes = 0;
440
}
441
442
result.d->data.truncate(readBytes);
443
return
result;
444
}
445
446
/*!
447
Receives a datagram no larger than \a maxSize bytes and stores
448
it in \a data. The sender's host address and port is stored in
449
*\a address and *\a port (unless the pointers are \nullptr).
450
451
Returns the size of the datagram on success; otherwise returns
452
-1.
453
454
If \a maxSize is too small, the rest of the datagram will be
455
lost. To avoid loss of data, call pendingDatagramSize() to
456
determine the size of the pending datagram before attempting to
457
read it. If \a maxSize is 0, the datagram will be discarded.
458
459
\sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
460
*/
461
qint64 QUdpSocket::readDatagram(
char
*data, qint64 maxSize, QHostAddress *address,
462
quint16 *port)
463
{
464
Q_D(QUdpSocket);
465
466
#
if
defined
QUDPSOCKET_DEBUG
467
qDebug(
"QUdpSocket::readDatagram(%p, %llu, %p, %p)"
, data, maxSize, address, port);
468
#
endif
469
QT_CHECK_BOUND
(
"QUdpSocket::readDatagram()"
, -1);
470
471
qint64 readBytes;
472
if
(address || port) {
473
QIpPacketHeader header;
474
readBytes = d->socketEngine->readDatagram(data, maxSize, &header,
475
QAbstractSocketEngine::WantDatagramSender);
476
if
(address)
477
*address = header.senderAddress;
478
if
(port)
479
*port = header.senderPort;
480
}
else
{
481
readBytes = d->socketEngine->readDatagram(data, maxSize);
482
}
483
484
d->hasPendingData =
false
;
485
d->hasPendingDatagram =
false
;
486
d->socketEngine->setReadNotificationEnabled(
true
);
487
if
(readBytes < 0) {
488
if
(readBytes == -2) {
489
// No pending datagram. Treat as a temporary error.
490
d->setErrorAndEmit(QAbstractSocket::TemporaryError,
491
tr(
"No datagram available for reading"
));
492
return
-1;
493
}
494
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
495
}
496
return
readBytes;
497
}
498
499
#
endif
// QT_NO_UDPSOCKET
500
501
QT_END_NAMESPACE
502
503
#
include
"moc_qudpsocket.cpp"
QT_CHECK_BOUND
#define QT_CHECK_BOUND(function, a)
Definition
qudpsocket.cpp:76
qtbase
src
network
socket
qudpsocket.cpp
Generated on
for Qt by
1.18.0