1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | //#define QTCPSERVER_DEBUG |
5 | |
6 | /*! \class QTcpServer |
7 | |
8 | \brief The QTcpServer class provides a TCP-based server. |
9 | |
10 | \reentrant |
11 | \ingroup network |
12 | \inmodule QtNetwork |
13 | |
14 | This class makes it possible to accept incoming TCP connections. |
15 | You can specify the port or have QTcpServer pick one |
16 | automatically. You can listen on a specific address or on all the |
17 | machine's addresses. |
18 | |
19 | Call listen() to have the server listen for incoming connections. |
20 | The newConnection() signal is then emitted each time a client |
21 | connects to the server. When the client connection has been added |
22 | to the pending connection queue using the addPendingConnection() |
23 | function, the pendingConnectionAvailable() signal is emitted. |
24 | |
25 | Call nextPendingConnection() to accept the pending connection as |
26 | a connected QTcpSocket. The function returns a pointer to a |
27 | QTcpSocket in QAbstractSocket::ConnectedState that you can use for |
28 | communicating with the client. |
29 | |
30 | If an error occurs, serverError() returns the type of error, and |
31 | errorString() can be called to get a human readable description of |
32 | what happened. |
33 | |
34 | When listening for connections, the address and port on which the |
35 | server is listening are available as serverAddress() and |
36 | serverPort(). |
37 | |
38 | Calling close() makes QTcpServer stop listening for incoming |
39 | connections. |
40 | |
41 | Although QTcpServer is mostly designed for use with an event |
42 | loop, it's possible to use it without one. In that case, you must |
43 | use waitForNewConnection(), which blocks until either a |
44 | connection is available or a timeout expires. |
45 | |
46 | \sa QTcpSocket, {Fortune Server}, {Threaded Fortune Server}, |
47 | {Torrent Example} |
48 | */ |
49 | |
50 | /*! \fn void QTcpServer::newConnection() |
51 | |
52 | This signal is emitted every time a new connection is available, regardless |
53 | of whether it has been added to the pending connections queue or not. |
54 | |
55 | \sa hasPendingConnections(), nextPendingConnection() |
56 | */ |
57 | |
58 | /*! \fn void QTcpServer::pendingConnectionAvailable() |
59 | |
60 | This signal is emitted every time a new connection has been added to the |
61 | pending connections queue. |
62 | |
63 | \sa hasPendingConnections(), nextPendingConnection() |
64 | \since 6.4 |
65 | */ |
66 | |
67 | /*! \fn void QTcpServer::acceptError(QAbstractSocket::SocketError socketError) |
68 | \since 5.0 |
69 | |
70 | This signal is emitted when accepting a new connection results in an error. |
71 | The \a socketError parameter describes the type of error that occurred. |
72 | |
73 | \sa pauseAccepting(), resumeAccepting() |
74 | */ |
75 | |
76 | #include "qtcpserver.h" |
77 | #include "qtcpserver_p.h" |
78 | |
79 | #include "qalgorithms.h" |
80 | #include "qhostaddress.h" |
81 | #include "qlist.h" |
82 | #include "qpointer.h" |
83 | #include "qabstractsocketengine_p.h" |
84 | #include "qtcpsocket.h" |
85 | #include "qnetworkproxy.h" |
86 | |
87 | QT_BEGIN_NAMESPACE |
88 | |
89 | #define Q_CHECK_SOCKETENGINE(returnValue) do { \ |
90 | if (!d->socketEngine) { \ |
91 | return returnValue; \ |
92 | } } while (0) |
93 | |
94 | /*! \internal |
95 | */ |
96 | QTcpServerPrivate::QTcpServerPrivate() |
97 | : port(0) |
98 | , socketType(QAbstractSocket::UnknownSocketType) |
99 | , state(QAbstractSocket::UnconnectedState) |
100 | , socketEngine(nullptr) |
101 | , serverSocketError(QAbstractSocket::UnknownSocketError) |
102 | , maxConnections(30) |
103 | { |
104 | } |
105 | |
106 | /*! \internal |
107 | */ |
108 | QTcpServerPrivate::~QTcpServerPrivate() |
109 | { |
110 | } |
111 | |
112 | #ifndef QT_NO_NETWORKPROXY |
113 | /*! \internal |
114 | |
115 | Resolve the proxy to its final value. |
116 | */ |
117 | QNetworkProxy QTcpServerPrivate::resolveProxy(const QHostAddress &address, quint16 port) |
118 | { |
119 | if (address.isLoopback()) |
120 | return QNetworkProxy::NoProxy; |
121 | |
122 | QList<QNetworkProxy> proxies; |
123 | if (proxy.type() != QNetworkProxy::DefaultProxy) { |
124 | // a non-default proxy was set with setProxy |
125 | proxies << proxy; |
126 | } else { |
127 | // try the application settings instead |
128 | QNetworkProxyQuery query(port, QString(), |
129 | socketType == QAbstractSocket::SctpSocket ? |
130 | QNetworkProxyQuery::SctpServer : |
131 | QNetworkProxyQuery::TcpServer); |
132 | proxies = QNetworkProxyFactory::proxyForQuery(query); |
133 | } |
134 | |
135 | // return the first that we can use |
136 | for (const QNetworkProxy &p : std::as_const(t&: proxies)) { |
137 | if (socketType == QAbstractSocket::TcpSocket && |
138 | (p.capabilities() & QNetworkProxy::ListeningCapability) != 0) |
139 | return p; |
140 | |
141 | if (socketType == QAbstractSocket::SctpSocket && |
142 | (p.capabilities() & QNetworkProxy::SctpListeningCapability) != 0) |
143 | return p; |
144 | } |
145 | |
146 | // no proxy found |
147 | // DefaultProxy will raise an error |
148 | return QNetworkProxy(QNetworkProxy::DefaultProxy); |
149 | } |
150 | #endif |
151 | |
152 | /*! \internal |
153 | */ |
154 | void QTcpServerPrivate::configureCreatedSocket() |
155 | { |
156 | #if defined(Q_OS_UNIX) |
157 | // Under Unix, we want to be able to bind to the port, even if a socket on |
158 | // the same address-port is in TIME_WAIT. Under Windows this is possible |
159 | // anyway -- furthermore, the meaning of reusable on Windows is different: |
160 | // it means that you can use the same address-port for multiple listening |
161 | // sockets. |
162 | // Don't abort though if we can't set that option. For example the socks |
163 | // engine doesn't support that option, but that shouldn't prevent us from |
164 | // trying to bind/listen. |
165 | socketEngine->setOption(option: QAbstractSocketEngine::AddressReusable, value: 1); |
166 | #endif |
167 | } |
168 | |
169 | /*! \internal |
170 | */ |
171 | void QTcpServerPrivate::readNotification() |
172 | { |
173 | Q_Q(QTcpServer); |
174 | for (;;) { |
175 | if (totalPendingConnections() >= maxConnections) { |
176 | #if defined (QTCPSERVER_DEBUG) |
177 | qDebug("QTcpServerPrivate::_q_processIncomingConnection() too many connections" ); |
178 | #endif |
179 | if (socketEngine->isReadNotificationEnabled()) |
180 | socketEngine->setReadNotificationEnabled(false); |
181 | return; |
182 | } |
183 | |
184 | qintptr descriptor = socketEngine->accept(); |
185 | if (descriptor == -1) { |
186 | if (socketEngine->error() != QAbstractSocket::TemporaryError) { |
187 | q->pauseAccepting(); |
188 | serverSocketError = socketEngine->error(); |
189 | serverSocketErrorString = socketEngine->errorString(); |
190 | emit q->acceptError(socketError: serverSocketError); |
191 | } |
192 | break; |
193 | } |
194 | #if defined (QTCPSERVER_DEBUG) |
195 | qDebug("QTcpServerPrivate::_q_processIncomingConnection() accepted socket %i" , descriptor); |
196 | #endif |
197 | QPointer<QTcpServer> that = q; |
198 | q->incomingConnection(handle: descriptor); |
199 | |
200 | if (that) |
201 | emit q->newConnection(); |
202 | |
203 | if (!that || !q->isListening()) |
204 | return; |
205 | } |
206 | } |
207 | |
208 | /*! |
209 | \internal |
210 | Return the amount of sockets currently in queue for the server. |
211 | This is to make maxPendingConnections work properly with servers that don't |
212 | necessarily have 'ready-to-go' sockets as soon as they connect, |
213 | e.g. QSslServer. |
214 | By default we just return pendingConnections.size(), which is equivalent to |
215 | what it did before. |
216 | */ |
217 | int QTcpServerPrivate::totalPendingConnections() const |
218 | { |
219 | return int(pendingConnections.size()); |
220 | } |
221 | |
222 | /*! |
223 | Constructs a QTcpServer object. |
224 | |
225 | \a parent is passed to the QObject constructor. |
226 | |
227 | \sa listen(), setSocketDescriptor() |
228 | */ |
229 | QTcpServer::QTcpServer(QObject *parent) |
230 | : QObject(*new QTcpServerPrivate, parent) |
231 | { |
232 | Q_D(QTcpServer); |
233 | #if defined(QTCPSERVER_DEBUG) |
234 | qDebug("QTcpServer::QTcpServer(%p)" , parent); |
235 | #endif |
236 | d->socketType = QAbstractSocket::TcpSocket; |
237 | } |
238 | |
239 | /*! |
240 | Destroys the QTcpServer object. If the server is listening for |
241 | connections, the socket is automatically closed. |
242 | |
243 | Any client \l{QTcpSocket}s that are still connected must either |
244 | disconnect or be reparented before the server is deleted. |
245 | |
246 | \sa close() |
247 | */ |
248 | QTcpServer::~QTcpServer() |
249 | { |
250 | #if defined(QTCPSERVER_DEBUG) |
251 | qDebug("QTcpServer::~QTcpServer()" ); |
252 | #endif |
253 | close(); |
254 | } |
255 | |
256 | /*! \internal |
257 | |
258 | Constructs a new server object with socket of type \a socketType. The \a |
259 | parent argument is passed to QObject's constructor. |
260 | */ |
261 | QTcpServer::QTcpServer(QAbstractSocket::SocketType socketType, QTcpServerPrivate &dd, |
262 | QObject *parent) : QObject(dd, parent) |
263 | { |
264 | Q_D(QTcpServer); |
265 | #if defined(QTCPSERVER_DEBUG) |
266 | qDebug("QTcpServer::QTcpServer(%sSocket, QTcpServerPrivate == %p, parent == %p)" , |
267 | socketType == QAbstractSocket::TcpSocket ? "Tcp" |
268 | : socketType == QAbstractSocket::UdpSocket ? "Udp" |
269 | : socketType == QAbstractSocket::SctpSocket ? "Sctp" |
270 | : "Unknown" , &dd, parent); |
271 | #endif |
272 | d->socketType = socketType; |
273 | } |
274 | |
275 | /*! |
276 | Tells the server to listen for incoming connections on address \a |
277 | address and port \a port. If \a port is 0, a port is chosen |
278 | automatically. If \a address is QHostAddress::Any, the server |
279 | will listen on all network interfaces. |
280 | |
281 | Returns \c true on success; otherwise returns \c false. |
282 | |
283 | \sa isListening() |
284 | */ |
285 | bool QTcpServer::listen(const QHostAddress &address, quint16 port) |
286 | { |
287 | Q_D(QTcpServer); |
288 | if (d->state == QAbstractSocket::ListeningState) { |
289 | qWarning(msg: "QTcpServer::listen() called when already listening" ); |
290 | return false; |
291 | } |
292 | |
293 | QAbstractSocket::NetworkLayerProtocol proto = address.protocol(); |
294 | QHostAddress addr = address; |
295 | |
296 | #ifdef QT_NO_NETWORKPROXY |
297 | static const QNetworkProxy &proxy = *(QNetworkProxy *)0; |
298 | #else |
299 | QNetworkProxy proxy = d->resolveProxy(address: addr, port); |
300 | #endif |
301 | |
302 | delete d->socketEngine; |
303 | d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketType: d->socketType, proxy, parent: this); |
304 | if (!d->socketEngine) { |
305 | d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError; |
306 | d->serverSocketErrorString = tr(s: "Operation on socket is not supported" ); |
307 | return false; |
308 | } |
309 | if (!d->socketEngine->initialize(type: d->socketType, protocol: proto)) { |
310 | d->serverSocketError = d->socketEngine->error(); |
311 | d->serverSocketErrorString = d->socketEngine->errorString(); |
312 | return false; |
313 | } |
314 | proto = d->socketEngine->protocol(); |
315 | if (addr.protocol() == QAbstractSocket::AnyIPProtocol && proto == QAbstractSocket::IPv4Protocol) |
316 | addr = QHostAddress::AnyIPv4; |
317 | |
318 | d->configureCreatedSocket(); |
319 | |
320 | if (!d->socketEngine->bind(address: addr, port)) { |
321 | d->serverSocketError = d->socketEngine->error(); |
322 | d->serverSocketErrorString = d->socketEngine->errorString(); |
323 | return false; |
324 | } |
325 | |
326 | if (!d->socketEngine->listen(backlog: d->listenBacklog)) { |
327 | d->serverSocketError = d->socketEngine->error(); |
328 | d->serverSocketErrorString = d->socketEngine->errorString(); |
329 | return false; |
330 | } |
331 | |
332 | d->socketEngine->setReceiver(d); |
333 | d->socketEngine->setReadNotificationEnabled(true); |
334 | |
335 | d->state = QAbstractSocket::ListeningState; |
336 | d->address = d->socketEngine->localAddress(); |
337 | d->port = d->socketEngine->localPort(); |
338 | |
339 | #if defined (QTCPSERVER_DEBUG) |
340 | qDebug("QTcpServer::listen(%i, \"%s\") == true (listening on port %i)" , port, |
341 | address.toString().toLatin1().constData(), d->socketEngine->localPort()); |
342 | #endif |
343 | return true; |
344 | } |
345 | |
346 | /*! |
347 | Returns \c true if the server is currently listening for incoming |
348 | connections; otherwise returns \c false. |
349 | |
350 | \sa listen() |
351 | */ |
352 | bool QTcpServer::isListening() const |
353 | { |
354 | Q_D(const QTcpServer); |
355 | Q_CHECK_SOCKETENGINE(false); |
356 | return d->socketEngine->state() == QAbstractSocket::ListeningState; |
357 | } |
358 | |
359 | /*! |
360 | Closes the server. The server will no longer listen for incoming |
361 | connections. |
362 | |
363 | \sa listen() |
364 | */ |
365 | void QTcpServer::close() |
366 | { |
367 | Q_D(QTcpServer); |
368 | |
369 | qDeleteAll(c: d->pendingConnections); |
370 | d->pendingConnections.clear(); |
371 | |
372 | if (d->socketEngine) { |
373 | d->socketEngine->close(); |
374 | QT_TRY { |
375 | d->socketEngine->deleteLater(); |
376 | } QT_CATCH(const std::bad_alloc &) { |
377 | // in out of memory situations, the socketEngine |
378 | // will be deleted in ~QTcpServer (it's a child-object of this) |
379 | } |
380 | d->socketEngine = nullptr; |
381 | } |
382 | |
383 | d->state = QAbstractSocket::UnconnectedState; |
384 | } |
385 | |
386 | /*! |
387 | Returns the native socket descriptor the server uses to listen |
388 | for incoming instructions, or -1 if the server is not listening. |
389 | |
390 | If the server is using QNetworkProxy, the returned descriptor may |
391 | not be usable with native socket functions. |
392 | |
393 | \sa setSocketDescriptor(), isListening() |
394 | */ |
395 | qintptr QTcpServer::socketDescriptor() const |
396 | { |
397 | Q_D(const QTcpServer); |
398 | Q_CHECK_SOCKETENGINE(-1); |
399 | return d->socketEngine->socketDescriptor(); |
400 | } |
401 | |
402 | /*! |
403 | Sets the socket descriptor this server should use when listening |
404 | for incoming connections to \a socketDescriptor. Returns \c true if |
405 | the socket is set successfully; otherwise returns \c false. |
406 | |
407 | The socket is assumed to be in listening state. |
408 | |
409 | \sa socketDescriptor(), isListening() |
410 | */ |
411 | bool QTcpServer::setSocketDescriptor(qintptr socketDescriptor) |
412 | { |
413 | Q_D(QTcpServer); |
414 | if (isListening()) { |
415 | qWarning(msg: "QTcpServer::setSocketDescriptor() called when already listening" ); |
416 | return false; |
417 | } |
418 | |
419 | if (d->socketEngine) |
420 | delete d->socketEngine; |
421 | d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, parent: this); |
422 | if (!d->socketEngine) { |
423 | d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError; |
424 | d->serverSocketErrorString = tr(s: "Operation on socket is not supported" ); |
425 | return false; |
426 | } |
427 | if (!d->socketEngine->initialize(socketDescriptor, socketState: QAbstractSocket::ListeningState)) { |
428 | d->serverSocketError = d->socketEngine->error(); |
429 | d->serverSocketErrorString = d->socketEngine->errorString(); |
430 | #if defined (QTCPSERVER_DEBUG) |
431 | qDebug("QTcpServer::setSocketDescriptor(%i) failed (%s)" , socketDescriptor, |
432 | d->serverSocketErrorString.toLatin1().constData()); |
433 | #endif |
434 | return false; |
435 | } |
436 | |
437 | d->socketEngine->setReceiver(d); |
438 | d->socketEngine->setReadNotificationEnabled(true); |
439 | |
440 | d->state = d->socketEngine->state(); |
441 | d->address = d->socketEngine->localAddress(); |
442 | d->port = d->socketEngine->localPort(); |
443 | |
444 | #if defined (QTCPSERVER_DEBUG) |
445 | qDebug("QTcpServer::setSocketDescriptor(%i) succeeded." , socketDescriptor); |
446 | #endif |
447 | return true; |
448 | } |
449 | |
450 | /*! |
451 | Returns the server's port if the server is listening for |
452 | connections; otherwise returns 0. |
453 | |
454 | \sa serverAddress(), listen() |
455 | */ |
456 | quint16 QTcpServer::serverPort() const |
457 | { |
458 | Q_D(const QTcpServer); |
459 | Q_CHECK_SOCKETENGINE(0); |
460 | return d->socketEngine->localPort(); |
461 | } |
462 | |
463 | /*! |
464 | Returns the server's address if the server is listening for |
465 | connections; otherwise returns QHostAddress::Null. |
466 | |
467 | \sa serverPort(), listen() |
468 | */ |
469 | QHostAddress QTcpServer::serverAddress() const |
470 | { |
471 | Q_D(const QTcpServer); |
472 | Q_CHECK_SOCKETENGINE(QHostAddress(QHostAddress::Null)); |
473 | return d->socketEngine->localAddress(); |
474 | } |
475 | |
476 | /*! |
477 | Waits for at most \a msec milliseconds or until an incoming |
478 | connection is available. Returns \c true if a connection is |
479 | available; otherwise returns \c false. If the operation timed out |
480 | and \a timedOut is not \nullptr, *\a timedOut will be set to true. |
481 | |
482 | This is a blocking function call. Its use is disadvised in a |
483 | single-threaded GUI application, since the whole application will |
484 | stop responding until the function returns. |
485 | waitForNewConnection() is mostly useful when there is no event |
486 | loop available. |
487 | |
488 | The non-blocking alternative is to connect to the newConnection() |
489 | signal. |
490 | |
491 | If msec is -1, this function will not time out. |
492 | |
493 | \sa hasPendingConnections(), nextPendingConnection() |
494 | */ |
495 | bool QTcpServer::waitForNewConnection(int msec, bool *timedOut) |
496 | { |
497 | Q_D(QTcpServer); |
498 | if (d->state != QAbstractSocket::ListeningState) |
499 | return false; |
500 | |
501 | if (!d->socketEngine->waitForRead(msecs: msec, timedOut)) { |
502 | d->serverSocketError = d->socketEngine->error(); |
503 | d->serverSocketErrorString = d->socketEngine->errorString(); |
504 | return false; |
505 | } |
506 | |
507 | if (timedOut && *timedOut) |
508 | return false; |
509 | |
510 | d->readNotification(); |
511 | |
512 | return true; |
513 | } |
514 | |
515 | /*! |
516 | Returns \c true if the server has a pending connection; otherwise |
517 | returns \c false. |
518 | |
519 | \sa nextPendingConnection(), setMaxPendingConnections() |
520 | */ |
521 | bool QTcpServer::hasPendingConnections() const |
522 | { |
523 | return !d_func()->pendingConnections.isEmpty(); |
524 | } |
525 | |
526 | /*! |
527 | Returns the next pending connection as a connected QTcpSocket |
528 | object. |
529 | |
530 | The socket is created as a child of the server, which means that |
531 | it is automatically deleted when the QTcpServer object is |
532 | destroyed. It is still a good idea to delete the object |
533 | explicitly when you are done with it, to avoid wasting memory. |
534 | |
535 | \nullptr is returned if this function is called when there are no pending |
536 | connections. |
537 | |
538 | \note The returned QTcpSocket object cannot be used from another |
539 | thread. If you want to use an incoming connection from another thread, |
540 | you need to override incomingConnection(). |
541 | |
542 | \sa hasPendingConnections() |
543 | */ |
544 | QTcpSocket *QTcpServer::nextPendingConnection() |
545 | { |
546 | Q_D(QTcpServer); |
547 | if (d->pendingConnections.isEmpty()) |
548 | return nullptr; |
549 | |
550 | if (!d->socketEngine) { |
551 | qWarning(msg: "QTcpServer::nextPendingConnection() called while not listening" ); |
552 | } else if (!d->socketEngine->isReadNotificationEnabled()) { |
553 | d->socketEngine->setReadNotificationEnabled(true); |
554 | } |
555 | |
556 | return d->pendingConnections.takeFirst(); |
557 | } |
558 | |
559 | /*! |
560 | This virtual function is called by QTcpServer when a new |
561 | connection is available. The \a socketDescriptor argument is the |
562 | native socket descriptor for the accepted connection. |
563 | |
564 | The base implementation creates a QTcpSocket, sets the socket |
565 | descriptor and then stores the QTcpSocket in an internal list of |
566 | pending connections. Finally newConnection() is emitted. |
567 | |
568 | Reimplement this function to alter the server's behavior when a |
569 | connection is available. |
570 | |
571 | If this server is using QNetworkProxy then the \a socketDescriptor |
572 | may not be usable with native socket functions, and should only be |
573 | used with QTcpSocket::setSocketDescriptor(). |
574 | |
575 | \note If another socket is created in the reimplementation |
576 | of this method, it needs to be added to the Pending Connections mechanism |
577 | by calling addPendingConnection(). |
578 | |
579 | \note If you want to handle an incoming connection as a new QTcpSocket |
580 | object in another thread you have to pass the socketDescriptor |
581 | to the other thread and create the QTcpSocket object there and |
582 | use its setSocketDescriptor() method. |
583 | |
584 | \sa newConnection(), nextPendingConnection(), addPendingConnection() |
585 | */ |
586 | void QTcpServer::incomingConnection(qintptr socketDescriptor) |
587 | { |
588 | #if defined (QTCPSERVER_DEBUG) |
589 | qDebug("QTcpServer::incomingConnection(%i)" , socketDescriptor); |
590 | #endif |
591 | |
592 | QTcpSocket *socket = new QTcpSocket(this); |
593 | socket->setSocketDescriptor(socketDescriptor); |
594 | addPendingConnection(socket); |
595 | } |
596 | |
597 | /*! |
598 | This function is called by QTcpServer::incomingConnection() |
599 | to add the \a socket to the list of pending incoming connections. |
600 | |
601 | \note Don't forget to call this member from reimplemented |
602 | incomingConnection() if you do not want to break the |
603 | Pending Connections mechanism. This function emits the |
604 | pendingConnectionAvailable() signal after the socket has been |
605 | added. |
606 | |
607 | \sa incomingConnection(), pendingConnectionAvailable() |
608 | \since 4.7 |
609 | */ |
610 | void QTcpServer::addPendingConnection(QTcpSocket* socket) |
611 | { |
612 | d_func()->pendingConnections.append(t: socket); |
613 | emit pendingConnectionAvailable(QPrivateSignal()); |
614 | } |
615 | |
616 | /*! |
617 | Sets the maximum number of pending accepted connections to \a |
618 | numConnections. QTcpServer will accept no more than \a |
619 | numConnections incoming connections before |
620 | nextPendingConnection() is called. By default, the limit is 30 |
621 | pending connections. |
622 | |
623 | Clients may still able to connect after the server has reached |
624 | its maximum number of pending connections (i.e., QTcpSocket can |
625 | still emit the connected() signal). QTcpServer will stop |
626 | accepting the new connections, but the operating system may |
627 | still keep them in queue. |
628 | |
629 | \sa maxPendingConnections(), hasPendingConnections() |
630 | */ |
631 | void QTcpServer::setMaxPendingConnections(int numConnections) |
632 | { |
633 | d_func()->maxConnections = numConnections; |
634 | } |
635 | |
636 | /*! |
637 | Returns the maximum number of pending accepted connections. The |
638 | default is 30. |
639 | |
640 | \sa setMaxPendingConnections(), hasPendingConnections() |
641 | */ |
642 | int QTcpServer::maxPendingConnections() const |
643 | { |
644 | return d_func()->maxConnections; |
645 | } |
646 | |
647 | /*! |
648 | Sets the backlog queue size of to be accepted connections to \a |
649 | size. The operating system might reduce or ignore this value. |
650 | By default, the queue size is 50. |
651 | |
652 | \note This property must be set prior to calling listen(). |
653 | |
654 | \since 6.3 |
655 | |
656 | \sa listenBacklogSize() |
657 | */ |
658 | void QTcpServer::setListenBacklogSize(int size) |
659 | { |
660 | d_func()->listenBacklog = size; |
661 | } |
662 | |
663 | /*! |
664 | Returns the backlog queue size of to be accepted connections. |
665 | |
666 | \since 6.3 |
667 | |
668 | \sa setListenBacklogSize() |
669 | */ |
670 | int QTcpServer::listenBacklogSize() const |
671 | { |
672 | return d_func()->listenBacklog; |
673 | } |
674 | |
675 | /*! |
676 | Returns an error code for the last error that occurred. |
677 | |
678 | \sa errorString() |
679 | */ |
680 | QAbstractSocket::SocketError QTcpServer::serverError() const |
681 | { |
682 | return d_func()->serverSocketError; |
683 | } |
684 | |
685 | /*! |
686 | Returns a human readable description of the last error that |
687 | occurred. |
688 | |
689 | \sa serverError() |
690 | */ |
691 | QString QTcpServer::errorString() const |
692 | { |
693 | return d_func()->serverSocketErrorString; |
694 | } |
695 | |
696 | /*! |
697 | \since 5.0 |
698 | |
699 | Pauses accepting new connections. Queued connections will remain in queue. |
700 | |
701 | \sa resumeAccepting() |
702 | */ |
703 | void QTcpServer::pauseAccepting() |
704 | { |
705 | d_func()->socketEngine->setReadNotificationEnabled(false); |
706 | } |
707 | |
708 | /*! |
709 | \since 5.0 |
710 | |
711 | Resumes accepting new connections. |
712 | |
713 | \sa pauseAccepting() |
714 | */ |
715 | void QTcpServer::resumeAccepting() |
716 | { |
717 | d_func()->socketEngine->setReadNotificationEnabled(true); |
718 | } |
719 | |
720 | #ifndef QT_NO_NETWORKPROXY |
721 | /*! |
722 | \since 4.1 |
723 | |
724 | Sets the explicit network proxy for this socket to \a networkProxy. |
725 | |
726 | To disable the use of a proxy for this socket, use the |
727 | QNetworkProxy::NoProxy proxy type: |
728 | |
729 | \snippet code/src_network_socket_qtcpserver.cpp 0 |
730 | |
731 | \sa proxy(), QNetworkProxy |
732 | */ |
733 | void QTcpServer::setProxy(const QNetworkProxy &networkProxy) |
734 | { |
735 | Q_D(QTcpServer); |
736 | d->proxy = networkProxy; |
737 | } |
738 | |
739 | /*! |
740 | \since 4.1 |
741 | |
742 | Returns the network proxy for this socket. |
743 | By default QNetworkProxy::DefaultProxy is used. |
744 | |
745 | \sa setProxy(), QNetworkProxy |
746 | */ |
747 | QNetworkProxy QTcpServer::proxy() const |
748 | { |
749 | Q_D(const QTcpServer); |
750 | return d->proxy; |
751 | } |
752 | #endif // QT_NO_NETWORKPROXY |
753 | |
754 | QT_END_NAMESPACE |
755 | |
756 | #include "moc_qtcpserver.cpp" |
757 | |
758 | |