📄 qtcpserver.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtNetwork module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************///#define QTCPSERVER_DEBUG/*! \class QTcpServer \brief The QTcpServer class provides a TCP-based server. \reentrant \ingroup io \module network This class makes it possible to accept incoming TCP connections. You can specify the port or have QTcpServer pick one automatically. You can listen on a specific address or on all the machine's addresses. Call listen() to have the server listen for incoming connections. The newConnection() signal is then emitted each time a client connects to the server. Call nextPendingConnection() to accept the pending connection as a connected QTcpSocket. The function returns a pointer to a QTcpSocket in QAbstractSocket::ConnectedState that you can use for communicating with the client. If an error occurs, serverError() returns the type of error, and errorString() can be called to get a human readable description of what happened. When listening for connections, the address and port on which the server is listening are available as serverAddress() and serverPort(). Calling close() makes QTcpServer stop listening for incoming connections. Although QTcpServer is mostly designed for use with an event loop, it's possible to use it without one. In that case, you must use waitForNewConnection(), which blocks until either a connection is available or a timeout expires. \sa QTcpSocket, {Fortune Server Example}, {Threaded Fortune Server Example}, {Loopback Example}, {Torrent Example}*//*! \fn void QTcpServer::newConnection() This signal is emitted every time a new connection is available. \sa hasPendingConnections(), nextPendingConnection()*/#include "private/qobject_p.h"#include "qalgorithms.h"#include "qhostaddress.h"#include "qlist.h"#include "qpointer.h"#include "qnativesocketengine_p.h"#include "qtcpserver.h"#include "qtcpsocket.h"#include "qnetworkproxy.h"#define Q_CHECK_SOCKETENGINE(returnValue) do { \ if (!d->socketEngine) { \ return returnValue; \ } } while (0)class QTcpServerPrivate : public QObjectPrivate, public QAbstractSocketEngineReceiver{ Q_DECLARE_PUBLIC(QTcpServer)public: QTcpServerPrivate(); ~QTcpServerPrivate(); QList<QTcpSocket *> pendingConnections; quint16 port; QHostAddress address; QAbstractSocket::SocketState state; QAbstractSocketEngine *socketEngine; QAbstractSocket::SocketError serverSocketError; QString serverSocketErrorString; int maxConnections;#ifndef QT_NO_NETWORKPROXY QNetworkProxy *proxy;#endif // from QAbstractSocketEngineReceiver void readNotification(); inline void writeNotification() {} inline void exceptionNotification() {} inline void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *) {}};/*! \internal*/QTcpServerPrivate::QTcpServerPrivate() : port(0) , state(QAbstractSocket::UnconnectedState) , socketEngine(0) , serverSocketError(QAbstractSocket::UnknownSocketError) , maxConnections(30)#ifndef QT_NO_NETWORKPROXY , proxy(0)#endif{}/*! \internal*/QTcpServerPrivate::~QTcpServerPrivate(){#ifndef QT_NO_NETWORKPROXY delete proxy;#endif}/*! \internal*/void QTcpServerPrivate::readNotification(){ Q_Q(QTcpServer); for (;;) { if (pendingConnections.count() >= maxConnections) {#if defined (QTCPSERVER_DEBUG) qDebug("QTcpServerPrivate::_q_processIncomingConnection() too many connections");#endif if (socketEngine->isReadNotificationEnabled()) socketEngine->setReadNotificationEnabled(false); return; } int descriptor = socketEngine->accept(); if (descriptor == -1) break;#if defined (QTCPSERVER_DEBUG) qDebug("QTcpServerPrivate::_q_processIncomingConnection() accepted socket %i", descriptor);#endif q->incomingConnection(descriptor); QPointer<QTcpServer> that = q; emit q->newConnection(); if (!that || !q->isListening()) return; }}/*! Constructs a QTcpServer object. \a parent is passed to the QObject constructor. \sa listen(), setSocketDescriptor()*/QTcpServer::QTcpServer(QObject *parent) : QObject(*new QTcpServerPrivate, parent){}/*! Destroys the QTcpServer object. If the server is listening for connections, the socket is automatically closed. Any client \l{QTcpSocket}s that are still connected must either disconnect or be reparented before the server is deleted. \sa close()*/QTcpServer::~QTcpServer(){ close();}/*! Tells the server to listen for incoming connections on address \a address and port \a port. If \a port is 0, a port is chosen automatically. If \a address is QHostAddress::Any, the server will listen on all network interfaces. Returns true on success; otherwise returns false. \sa isListening()*/bool QTcpServer::listen(const QHostAddress &address, quint16 port){ Q_D(QTcpServer); if (d->state == QAbstractSocket::ListeningState) { qWarning("QTcpServer::listen() called when already listening"); return false; } QAbstractSocket::NetworkLayerProtocol proto = address.protocol();#if defined(QT_NO_IPV6) if (proto == QAbstractSocket::IPv6Protocol) { // If we have no IPv6 support, then we will not be able to // listen on an IPv6 interface. d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError; d->serverSocketErrorString = tr("Socket operation unsupported"); return false; }#endif if (d->socketEngine) delete d->socketEngine; d->socketEngine = QAbstractSocketEngine::createSocketEngine(address, QAbstractSocket::TcpSocket, this); if (!d->socketEngine->initialize(QAbstractSocket::TcpSocket, proto)) { d->serverSocketError = d->socketEngine->error(); d->serverSocketErrorString = d->socketEngine->errorString(); return false; }#if defined(Q_OS_UNIX) // Under Unix, we want to be able to bind to the port, even if a socket on // the same address-port is in TIME_WAIT. Under Windows this is possible // anyway -- furthermore, the meaning of reusable on Windows is different: // it means that you can use the same address-port for multiple listening // sockets. // Don't abort though if we can't set that option. For example the socks // engine doesn't support that option, but that shouldn't prevent us from // trying to bind/listen. d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 1);#endif if (!d->socketEngine->bind(address, port)) { d->serverSocketError = d->socketEngine->error(); d->serverSocketErrorString = d->socketEngine->errorString(); return false; } if (!d->socketEngine->listen()) { d->serverSocketError = d->socketEngine->error(); d->serverSocketErrorString = d->socketEngine->errorString(); return false; } d->socketEngine->setReceiver(d); d->socketEngine->setReadNotificationEnabled(true); d->state = QAbstractSocket::ListeningState; d->address = d->socketEngine->localAddress(); d->port = d->socketEngine->localPort();#if defined (QTCPSERVER_DEBUG) qDebug("QTcpServer::listen(%i, \"%s\") == true (listening on port %i)", port, address.toString().toLatin1().constData(), d->socketEngine->localPort());#endif return true;}/*! Returns true if the server is currently listening for incoming connections; otherwise returns false. \sa listen()*/bool QTcpServer::isListening() const{ Q_D(const QTcpServer); Q_CHECK_SOCKETENGINE(false); return d->socketEngine->state() == QAbstractSocket::ListeningState;}/*!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -