⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 q3socket.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the Qt3Support 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.******************************************************************************/#include "q3socket.h"#ifndef QT_NO_NETWORK#include "q3ptrlist.h"#include "qtimer.h"#include "q3socketdevice.h"#include "q3dns.h"#include "private/q3membuf_p.h"#include <string.h>#ifndef NO_ERRNO_H#include <errno.h>#endif//#define Q3SOCKET_DEBUG/*  Perhaps this private functionality needs to be refactored.  Comment from Robert D Gatlin (Intel):    It would be nice to have the functionality inherent in Q3Socket available    as a separate class as a standard part of the Qt library, something along    the line of:      class QByteBuffer : public QIODevice { ... }    The same class could/would be used within Q3Socket for the Read/Write    buffers.    The above class could be used in the following way(s):	buffer.open( IO_WriteOnly | IO_Append );	buffer.writeBlock( a ); // a = QByteArray	buffer.close();	QByteArray b;	b.resize( buffer.size() );	buffer.open( IO_ReadOnly );	buffer.readBlock( b.data(), b.size() );	buffer.close();    But would also be useable with QDataStream (via QIODevice) with:	buffer.open( IO_WriteOnly | IO_Append );	QDataStream is( &buffer );	is << 100;	buffer.close();	buffer.open( IO_ReadOnly );	QDataStream os( &buffer );	Q_UINT32 x;	os >> x;	buffer.close();    The real usefulness is with any situations where data (QByteArray) arrives    incrementally (as in Q3Socket and filter case above).    I tried using QBuffer, but QBuffer does not trim bytes from the front of    the buffer in cases like:	QBuffer buf;	buf.open( IO_ReadOnly );	QDataStream ds( &buf );	Q_INT32 x;	ds >> x;	buf.close();    In the above case, buf.size() will be identical before and after the    operation with QDataStream. Based on the implementation of QBuffer, it    does not appear well suited for this kind of operation.*/// Private class for Q3Socketclass Q3SocketPrivate {public:    Q3SocketPrivate();   ~Q3SocketPrivate();    void closeSocket();    void close();    void connectionClosed();    void setSocketDevice( Q3Socket *q, Q3SocketDevice *device );    Q3Socket::State	state;			// connection state    QString		host;			// host name    Q_UINT16		port;			// host port    Q3SocketDevice      *socket;			// connection socket    QSocketNotifier     *rsn, *wsn;		// socket notifiers    Q3Membuf		rba;			// read buffer    Q_ULONG		readBufferSize;		// limit for the read buffer size    Q3PtrList<QByteArray> wba;			// list of write bufs    QHostAddress	addr;			// connection address    Q3ValueList<QHostAddress> addresses;		// alternatives looked up    QIODevice::Offset	wsize;			// write total buf size    QIODevice::Offset	windex;			// write index#ifndef QT_NO_DNS    Q3Dns	       *dns4;    Q3Dns	       *dns6;#endif    static Q3PtrList<Q3Socket> sn_read_alreadyCalled; // used to avoid unwanted recursion    Q3ValueList<QHostAddress> l4;    Q3ValueList<QHostAddress> l6;};Q3PtrList<Q3Socket> Q3SocketPrivate::sn_read_alreadyCalled;Q3SocketPrivate::Q3SocketPrivate()    : state(Q3Socket::Idle), host(QString::fromLatin1("")), port(0),      socket(0), rsn(0), wsn(0), readBufferSize(0), wsize(0), windex(0){#ifndef QT_NO_DNS    dns4 = 0;    dns6 = 0;#endif    wba.setAutoDelete( true );}Q3SocketPrivate::~Q3SocketPrivate(){    close();    delete socket;#ifndef QT_NO_DNS    delete dns4;    delete dns6;#endif}void Q3SocketPrivate::closeSocket(){    // Order is important here - the socket notifiers must go away    // before the socket does, otherwise libc or the kernel will    // become unhappy.    delete rsn;    rsn = 0;    delete wsn;    wsn = 0;    if ( socket )	socket->close();}void Q3SocketPrivate::close(){    closeSocket();    wsize = 0;    rba.clear(); wba.clear();    windex = 0;}void Q3SocketPrivate::connectionClosed(){    // We keep the open state in case there's unread incoming data    state = Q3Socket::Idle;    closeSocket();    wba.clear();    windex = wsize = 0;}void Q3SocketPrivate::setSocketDevice( Q3Socket *q, Q3SocketDevice *device ){    delete socket;    delete rsn;    delete wsn;    if ( device ) {	socket = device;    } else {	socket = new Q3SocketDevice( Q3SocketDevice::Stream,				    ( addr.isIPv4Address() ?				      Q3SocketDevice::IPv4 :				      Q3SocketDevice::IPv6 ), 0 );	socket->setBlocking( false );	socket->setAddressReusable( true );    }    rsn = new QSocketNotifier( socket->socket(),			       QSocketNotifier::Read, q, "read" );    wsn = new QSocketNotifier( socket->socket(),			       QSocketNotifier::Write, q, "write" );    QObject::connect( rsn, SIGNAL(activated(int)), q, SLOT(sn_read()) );    rsn->setEnabled( false );    QObject::connect( wsn, SIGNAL(activated(int)), q, SLOT(sn_write()) );    wsn->setEnabled( false );}/*!    \class Q3Socket q3socket.h    \brief The Q3Socket class provides a buffered TCP connection.    \compat    It provides a totally non-blocking QIODevice, and modifies and    extends the API of QIODevice with socket-specific code.    The functions you're likely to call most are connectToHost(),    bytesAvailable(), canReadLine() and the ones it inherits from    QIODevice.    connectToHost() is the most-used function. As its name implies,    it opens a connection to a named host.    Most network protocols are either packet-oriented or    line-oriented. canReadLine() indicates whether a connection    contains an entire unread line or not, and bytesAvailable()    returns the number of bytes available for reading.    The signals error(), connected(), readyRead() and    connectionClosed() inform you of the progress of the connection.    There are also some less commonly used signals. hostFound() is    emitted when connectToHost() has finished its DNS lookup and is    starting its TCP connection. delayedCloseFinished() is emitted    when close() succeeds. bytesWritten() is emitted when Q3Socket    moves data from its "to be written" queue into the TCP    implementation.    There are several access functions for the socket: state() returns    whether the object is idle, is doing a DNS lookup, is connecting,    has an operational connection, etc. address() and port() return    the IP address and port used for the connection. The peerAddress()    and peerPort() functions return the IP address and port used by    the peer, and peerName() returns the name of the peer (normally    the name that was passed to connectToHost()). socketDevice()    returns a pointer to the Q3SocketDevice used for this socket.    Q3Socket inherits QIODevice, and reimplements some functions. In    general, you can treat it as a QIODevice for writing, and mostly    also for reading. The match isn't perfect, since the QIODevice    API is designed for devices that are controlled by the same    machine, and an asynchronous peer-to-peer network connection isn't    quite like that. For example, there is nothing that matches    QIODevice::size() exactly. The documentation for open(), close(),    flush(), size(), at(), atEnd(), readBlock(), writeBlock(),    getch(), putch(), ungetch() and readLine() describes the    differences in detail.    \warning Q3Socket is not suitable for use in threads. If you need    to uses sockets in threads use the lower-level Q3SocketDevice class.    \sa Q3SocketDevice, QHostAddress, QSocketNotifier*//*!    Creates a Q3Socket object in Q3Socket::Idle state.    The \a parent and \a name arguments are passed on to the QObject    constructor.*/Q3Socket::Q3Socket( QObject *parent, const char *name )    : QIODevice( parent ){    setObjectName(QLatin1String(name));    d = new Q3SocketPrivate;    setSocketDevice( 0 );    resetStatus();}/*!    Destroys the socket. Closes the connection if necessary.    \sa close()*/Q3Socket::~Q3Socket(){#if defined(Q3SOCKET_DEBUG)    qDebug( "Q3Socket (%s): Destroy", name() );#endif    if ( state() != Idle )	close();    Q_ASSERT( d != 0 );    delete d;}/*!    Returns a pointer to the internal socket device.    There is normally no need to manipulate the socket device directly    since this class does the necessary setup for most applications.*/Q3SocketDevice *Q3Socket::socketDevice(){    return d->socket;}/*!    Sets the internal socket device to \a device. Passing a \a device    of 0 will cause the internal socket device to be used. Any    existing connection will be disconnected before using the new \a    device.    The new device should not be connected before being associated    with a Q3Socket; after setting the socket call connectToHost() to    make the connection.    This function is useful if you need to subclass Q3SocketDevice and    want to use the Q3Socket API, for example, to implement Unix domain    sockets.*/void Q3Socket::setSocketDevice( Q3SocketDevice *device ){    if ( state() != Idle )	close();    d->setSocketDevice( this, device );}/*!    \enum Q3Socket::State    This enum defines the connection states:    \value Idle if there is no connection    \value HostLookup during a DNS lookup    \value Connecting during TCP connection establishment    \value Connected when there is an operational connection    \value Closing if the socket is closing down, but is not yet closed.    \omitvalue Connection*//*!    Returns the current state of the socket connection.    \sa Q3Socket::State*/Q3Socket::State Q3Socket::state() const{    return d->state;}#ifndef QT_NO_DNS/*!    Attempts to make a connection to \a host on the specified \a port    and return immediately.    Any connection or pending connection is closed immediately, and    Q3Socket goes into the \c HostLookup state. When the lookup    succeeds, it emits hostFound(), starts a TCP connection and goes    into the \c Connecting state. Finally, when the connection    succeeds, it emits connected() and goes into the \c Connected    state. If there is an error at any point, it emits error().    \a host may be an IP address in string form, or it may be a DNS    name. Q3Socket will do a normal DNS lookup if required. Note that    \a port is in native byte order, unlike some other libraries.    \sa state()*/void Q3Socket::connectToHost( const QString &host, Q_UINT16 port ){#if defined(Q3SOCKET_DEBUG)    qDebug( "Q3Socket (%s)::connectToHost: host %s, port %d",	    name(), host.ascii(), port );#endif    setSocketIntern( -1 );    d->state = HostLookup;    d->host = host;    d->port = port;    d->dns4 = new Q3Dns( host, Q3Dns::A );    d->dns6 = new Q3Dns( host, Q3Dns::Aaaa );    // try if the address is already available (for faster connecting...)    tryConnecting();    if ( d->state == HostLookup ) {	connect( d->dns4, SIGNAL(resultsReady()),		 this, SLOT(tryConnecting()) );	connect( d->dns6, SIGNAL(resultsReady()),		 this, SLOT(tryConnecting()) );    }}#endif/*!    This private slots continues the connection process where    connectToHost() leaves off.*/void Q3Socket::tryConnecting(){#if defined(Q3SOCKET_DEBUG)    qDebug( "Q3Socket (%s)::tryConnecting()", name() );#endif    // ### this ifdef isn't correct - addresses() also does /etc/hosts and    // numeric-address-as-string handling.#ifndef QT_NO_DNS    if ( d->dns4 ) {	d->l4 = d->dns4->addresses();	if ( !d->l4.isEmpty() || !d->dns4->isWorking() ) {#if defined(Q3SOCKET_DEBUG)	    qDebug( "Q3Socket (%s)::tryConnecting: host %s, port %d: "		    "%d IPv4 addresses",		    name(), d->host.ascii(), d->port, d->l4.count() );#endif	    delete d->dns4;	    d->dns4 = 0;	}    }    if ( d->dns6 ) {	d->l6 = d->dns6->addresses();	if ( !d->l6.isEmpty() || !d->dns6->isWorking() ) {#if defined(Q3SOCKET_DEBUG)	    qDebug( "Q3Socket (%s)::tryConnecting: host %s, port %d: "		    "%d IPv6 addresses",		    name(), d->host.ascii(), d->port, d->l6.count() );#endif	    delete d->dns6;	    d->dns6 = 0;	}    }    if ( d->state == HostLookup ) {	if ( d->l4.isEmpty() && d->l6.isEmpty() &&	     !d->dns4 && !d->dns6 ) {	    // no results and we're not still looking: give up	    d->state = Idle;	    emit error( ErrHostNotFound );	    return;	}	if ( d->l4.isEmpty() && d->l6.isEmpty() ) {	    // no results (yet): try again later	    return;	}	// we've found something. press on with that. if we later find	// more, fine.	emit hostFound();	d->state = Connecting;    }    if ( d->state == Connecting ) {	d->addresses += d->l4;	d->addresses += d->l6;	d->l4.clear();	d->l6.clear();	// try one address at a time, falling back to the next one if	// there is a connection failure. (should also support a timeout,	// or do multiple TCP-level connects at a time, with staggered	// starts to avoid bandwidth waste and cause fewer	// "connect-and-abort" errors. but that later.)	bool stuck = true;	while( stuck ) {	    stuck = false;	    if ( d->socket &&		 d->socket->connect( d->addr, d->port ) == false ) {		if ( d->socket->error() == Q3SocketDevice::NoError ) {		    if ( d->wsn )			d->wsn->setEnabled( true );		    return; // not serious, try again later		}#if defined(Q3SOCKET_DEBUG)		qDebug( "Q3Socket (%s)::tryConnecting: "			"Gave up on IP address %s",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -