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