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