Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
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"
70
72
73#ifndef QT_NO_UDPSOCKET
74
75#define QT_CHECK_BOUND(function, a) do {
76 if (!isValid()) {
77 qWarning(function" called on a QUdpSocket when not in QUdpSocket::BoundState");
78 return (a);
79 } } while (0)
80
82{
83 Q_DECLARE_PUBLIC(QUdpSocket)
84
87public:
88 inline bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)
89 { return doEnsureInitialized(bindAddress, bindPort, QHostAddress()); }
90
91 inline bool ensureInitialized(const QHostAddress &remoteAddress)
92 { return doEnsureInitialized(QHostAddress(), 0, remoteAddress); }
93};
94
95bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
96 const QHostAddress &remoteAddress)
97{
98 const QHostAddress *address = &bindAddress;
99 QAbstractSocket::NetworkLayerProtocol proto = address->protocol();
100 if (proto == QUdpSocket::UnknownNetworkLayerProtocol) {
101 address = &remoteAddress;
102 proto = address->protocol();
103 }
104
105 // now check if the socket engine is initialized and to the right type
106 if (!socketEngine || !socketEngine->isValid()) {
107 resolveProxy(remoteAddress.toString(), bindPort);
108 if (!initSocketLayer(address->protocol()))
109 return false;
110 }
111
112 return true;
113}
114
115/*!
116 Creates a QUdpSocket object.
117
118 \a parent is passed to the QObject constructor.
119
120 \sa socketType()
121*/
122QUdpSocket::QUdpSocket(QObject *parent)
123 : QAbstractSocket(UdpSocket, *new QUdpSocketPrivate, parent)
124{
125 d_func()->isBuffered = false;
126}
127
128/*!
129 Destroys the socket, closing the connection if necessary.
130
131 \sa close()
132*/
133QUdpSocket::~QUdpSocket()
134{
135}
136
137#ifndef QT_NO_NETWORKINTERFACE
138
139/*!
140 \since 4.8
141
142 Joins the multicast group specified by \a groupAddress on the default
143 interface chosen by the operating system. The socket must be in BoundState,
144 otherwise an error occurs.
145
146 Note that if you are attempting to join an IPv4 group, your socket must not
147 be bound using IPv6 (or in dual mode, using QHostAddress::Any). You must use
148 QHostAddress::AnyIPv4 instead.
149
150 This function returns \c true if successful; otherwise it returns \c false
151 and sets the socket error accordingly.
152
153 \note Joining IPv6 multicast groups without an interface selection is not
154 supported in all operating systems. Consider using the overload where the
155 interface is specified.
156
157 \sa leaveMulticastGroup()
158*/
159bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress)
160{
161 return joinMulticastGroup(groupAddress, QNetworkInterface());
162}
163
164/*!
165 \since 4.8
166 \overload
167
168 Joins the multicast group address \a groupAddress on the interface \a
169 iface.
170
171 \sa leaveMulticastGroup()
172*/
173bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress,
174 const QNetworkInterface &iface)
175{
176 Q_D(QUdpSocket);
177 QT_CHECK_BOUND("QUdpSocket::joinMulticastGroup()", false);
178 return d->socketEngine->joinMulticastGroup(groupAddress, iface);
179}
180
181/*!
182 \since 4.8
183
184 Leaves the multicast group specified by \a groupAddress on the default
185 interface chosen by the operating system. The socket must be in BoundState,
186 otherwise an error occurs.
187
188 This function returns \c true if successful; otherwise it returns \c false and
189 sets the socket error accordingly.
190
191 \note This function should be called with the same arguments as were passed
192 to joinMulticastGroup().
193
194 \sa joinMulticastGroup()
195*/
196bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress)
197{
198 return leaveMulticastGroup(groupAddress, QNetworkInterface());
199}
200
201/*!
202 \since 4.8
203 \overload
204
205 Leaves the multicast group specified by \a groupAddress on the interface \a
206 iface.
207
208 \note This function should be called with the same arguments as were passed
209 to joinMulticastGroup().
210
211 \sa joinMulticastGroup()
212*/
213bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress,
214 const QNetworkInterface &iface)
215{
216 QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false);
217 return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
218}
219
220/*!
221 \since 4.8
222
223 Returns the interface for the outgoing interface for multicast datagrams.
224 This corresponds to the IP_MULTICAST_IF socket option for IPv4 sockets and
225 the IPV6_MULTICAST_IF socket option for IPv6 sockets. If no interface has
226 been previously set, this function returns an invalid QNetworkInterface.
227 The socket must be in BoundState, otherwise an invalid QNetworkInterface is
228 returned.
229
230 \sa setMulticastInterface()
231*/
232QNetworkInterface QUdpSocket::multicastInterface() const
233{
234 Q_D(const QUdpSocket);
235 QT_CHECK_BOUND("QUdpSocket::multicastInterface()", QNetworkInterface());
236 return d->socketEngine->multicastInterface();
237}
238
239/*!
240 \since 4.8
241
242 Sets the outgoing interface for multicast datagrams to the interface \a
243 iface. This corresponds to the IP_MULTICAST_IF socket option for IPv4
244 sockets and the IPV6_MULTICAST_IF socket option for IPv6 sockets. The
245 socket must be in BoundState, otherwise this function does nothing.
246
247 \sa multicastInterface(), joinMulticastGroup(), leaveMulticastGroup()
248*/
249void QUdpSocket::setMulticastInterface(const QNetworkInterface &iface)
250{
251 Q_D(QUdpSocket);
252 if (!isValid()) {
253 qWarning("QUdpSocket::setMulticastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState");
254 return;
255 }
256 d->socketEngine->setMulticastInterface(iface);
257}
258
259#endif // QT_NO_NETWORKINTERFACE
260
261/*!
262 Returns \c true if at least one datagram is waiting to be read;
263 otherwise returns \c false.
264
265 \sa pendingDatagramSize(), readDatagram()
266*/
267bool QUdpSocket::hasPendingDatagrams() const
268{
269 QT_CHECK_BOUND("QUdpSocket::hasPendingDatagrams()", false);
270 return d_func()->socketEngine->hasPendingDatagrams();
271}
272
273/*!
274 Returns the size of the first pending UDP datagram. If there is
275 no datagram available, this function returns -1.
276
277 \sa hasPendingDatagrams(), readDatagram()
278*/
279qint64 QUdpSocket::pendingDatagramSize() const
280{
281 QT_CHECK_BOUND("QUdpSocket::pendingDatagramSize()", -1);
282 return d_func()->socketEngine->pendingDatagramSize();
283}
284
285/*!
286 Sends the datagram at \a data of size \a size to the host
287 address \a address at port \a port. Returns the number of
288 bytes sent on success; otherwise returns -1.
289
290 Datagrams are always written as one block. The maximum size of a
291 datagram is highly platform-dependent, but can be as low as 8192
292 bytes. If the datagram is too large, this function will return -1
293 and error() will return DatagramTooLargeError.
294
295 Sending datagrams larger than 512 bytes is in general disadvised,
296 as even if they are sent successfully, they are likely to be
297 fragmented by the IP layer before arriving at their final
298 destination.
299
300 \warning Calling this function on a connected UDP socket may
301 result in an error and no packet being sent. If you are using a
302 connected socket, use write() to send datagrams.
303
304 \sa readDatagram(), write()
305*/
306qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address,
307 quint16 port)
308{
309 Q_D(QUdpSocket);
310#if defined QUDPSOCKET_DEBUG
311 qDebug("QUdpSocket::writeDatagram(%p, %llu, \"%s\", %i)", data, size,
312 address.toString().toLatin1().constData(), port);
313#endif
314 if (!d->doEnsureInitialized(QHostAddress::Any, 0, address))
315 return -1;
316 if (state() == UnconnectedState)
317 bind();
318
319 qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port));
320 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
321
322 if (sent >= 0) {
323 emit bytesWritten(sent);
324 } else {
325 if (sent == -2) {
326 // Socket engine reports EAGAIN. Treat as a temporary error.
327 d->setErrorAndEmit(QAbstractSocket::TemporaryError,
328 tr("Unable to send a datagram"));
329 return -1;
330 }
331 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
332 }
333 return sent;
334}
335
336/*!
337 \fn qint64 QUdpSocket::writeDatagram(const QByteArray &datagram,
338 const QHostAddress &host, quint16 port)
339 \overload
340
341 Sends the datagram \a datagram to the host address \a host and at
342 port \a port.
343
344 The function returns the number of bytes sent if it succeeded or -1 if it
345 encountered an error.
346*/
347
348/*!
349 \since 5.8
350 \overload
351
352 Sends the datagram \a datagram to the host address and port numbers
353 contained in \a datagram, using the network interface and hop count limits
354 also set there. If the destination address and port numbers are unset, this
355 function will send to the address that was passed to connectToHost().
356
357 If the destination address is IPv6 with a non-empty
358 \l{QHostAddress::scopeId()}{scope id} but differs from the interface index
359 in \a datagram, it is undefined which interface the operating system will
360 choose to send on.
361
362 The function returns the number of bytes sent if it succeeded or -1 if it
363 encountered an error.
364
365 \warning Calling this function on a connected UDP socket may
366 result in an error and no packet being sent. If you are using a
367 connected socket, use write() to send datagrams.
368
369 \sa QNetworkDatagram::setDestination(), QNetworkDatagram::setHopLimit(), QNetworkDatagram::setInterfaceIndex()
370*/
371qint64 QUdpSocket::writeDatagram(const QNetworkDatagram &datagram)
372{
373 Q_D(QUdpSocket);
374#if defined QUDPSOCKET_DEBUG
375 qDebug("QUdpSocket::writeDatagram(%p, %i, \"%s\", %i)",
376 datagram.d->data.constData(),
377 datagram.d->data.size(),
378 datagram.destinationAddress().toString().toLatin1().constData(),
379 datagram.destinationPort());
380#endif
381 if (!d->doEnsureInitialized(QHostAddress::Any, 0, datagram.destinationAddress()))
382 return -1;
383 if (state() == UnconnectedState)
384 bind();
385
386 qint64 sent = d->socketEngine->writeDatagram(datagram.d->data.constData(),
387 datagram.d->data.size(),
388 datagram.d->header);
389 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
390
391 if (sent >= 0) {
392 emit bytesWritten(sent);
393 } else {
394 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
395 }
396 return sent;
397}
398
399/*!
400 \since 5.8
401
402 Receives a datagram no larger than \a maxSize bytes and returns it in the
403 QNetworkDatagram object, along with the sender's host address and port. If
404 possible, this function will also try to determine the datagram's
405 destination address, port, and the number of hop counts at reception time.
406
407 On failure, returns a QNetworkDatagram that reports \l
408 {QNetworkDatagram::isValid()}{not valid}.
409
410 If \a maxSize is too small, the rest of the datagram will be lost. If \a
411 maxSize is 0, the datagram will be discarded. If \a maxSize is -1 (the
412 default), this function will attempt to read the entire datagram.
413
414 \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
415*/
416QNetworkDatagram QUdpSocket::receiveDatagram(qint64 maxSize)
417{
418 Q_D(QUdpSocket);
419
420#if defined QUDPSOCKET_DEBUG
421 qDebug("QUdpSocket::receiveDatagram(%lld)", maxSize);
422#endif
423 QT_CHECK_BOUND("QUdpSocket::receiveDatagram()", QNetworkDatagram());
424
425 if (maxSize < 0)
426 maxSize = d->socketEngine->pendingDatagramSize();
427 if (maxSize < 0)
428 return QNetworkDatagram();
429
430 QNetworkDatagram result(QByteArray(maxSize, Qt::Uninitialized));
431 qint64 readBytes = d->socketEngine->readDatagram(result.d->data.data(), maxSize, &result.d->header,
432 QAbstractSocketEngine::WantAll);
433 d->hasPendingData = false;
434 d->hasPendingDatagram = false;
435 d->socketEngine->setReadNotificationEnabled(true);
436 if (readBytes < 0) {
437 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
438 readBytes = 0;
439 }
440
441 result.d->data.truncate(readBytes);
442 return result;
443}
444
445/*!
446 Receives a datagram no larger than \a maxSize bytes and stores
447 it in \a data. The sender's host address and port is stored in
448 *\a address and *\a port (unless the pointers are \nullptr).
449
450 Returns the size of the datagram on success; otherwise returns
451 -1.
452
453 If \a maxSize is too small, the rest of the datagram will be
454 lost. To avoid loss of data, call pendingDatagramSize() to
455 determine the size of the pending datagram before attempting to
456 read it. If \a maxSize is 0, the datagram will be discarded.
457
458 \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
459*/
460qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address,
461 quint16 *port)
462{
463 Q_D(QUdpSocket);
464
465#if defined QUDPSOCKET_DEBUG
466 qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port);
467#endif
468 QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1);
469
470 qint64 readBytes;
471 if (address || port) {
472 QIpPacketHeader header;
473 readBytes = d->socketEngine->readDatagram(data, maxSize, &header,
474 QAbstractSocketEngine::WantDatagramSender);
475 if (address)
476 *address = header.senderAddress;
477 if (port)
478 *port = header.senderPort;
479 } else {
480 readBytes = d->socketEngine->readDatagram(data, maxSize);
481 }
482
483 d->hasPendingData = false;
484 d->hasPendingDatagram = false;
485 d->socketEngine->setReadNotificationEnabled(true);
486 if (readBytes < 0) {
487 if (readBytes == -2) {
488 // No pending datagram. Treat as a temporary error.
489 d->setErrorAndEmit(QAbstractSocket::TemporaryError,
490 tr("No datagram available for reading"));
491 return -1;
492 }
493 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
494 }
495 return readBytes;
496}
497
498#endif // QT_NO_UDPSOCKET
499
500QT_END_NAMESPACE
501
502#include "moc_qudpsocket.cpp"
bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)
bool ensureInitialized(const QHostAddress &remoteAddress)
#define QT_CHECK_BOUND(function, a)