📄 q3socket.cpp
字号:
name(), d->socket->peerAddress().toString().ascii() );#endif delete d->wsn; d->wsn = 0; delete d->rsn; d->rsn = 0; delete d->socket; d->socket = 0; if(d->addresses.isEmpty()) { emit error( ErrConnectionRefused ); return; } } // if the host has more addresses, try another some. if ( d->socket == 0 && !d->addresses.isEmpty() ) { d->addr = *d->addresses.begin(); d->addresses.remove( d->addresses.begin() ); d->setSocketDevice( this, 0 ); stuck = true;#if defined(Q3SOCKET_DEBUG) qDebug( "Q3Socket (%s)::tryConnecting: Trying IP address %s", name(), d->addr.toString().ascii() );#endif } }; // The socket write notifier will fire when the connection succeeds if ( d->wsn ) d->wsn->setEnabled( true ); }#endif}/*! \enum Q3Socket::Error This enum specifies the possible errors: \value ErrConnectionRefused if the connection was refused \value ErrHostNotFound if the host was not found \value ErrSocketRead if a read from the socket failed*//*! \fn void Q3Socket::error(int error) This signal is emitted after an error occurred. The \a error parameter is the \l Error value.*//*! \fn void Q3Socket::hostFound() This signal is emitted after connectToHost() has been called and the host lookup has succeeded. \sa connected()*//*! \fn void Q3Socket::connected() This signal is emitted after connectToHost() has been called and a connection has been successfully established. \sa connectToHost(), connectionClosed()*//*! \fn void Q3Socket::connectionClosed() This signal is emitted when the other end has closed the connection. The read buffers may contain buffered input data which you can read after the connection was closed. \sa connectToHost(), close()*//*! \fn void Q3Socket::delayedCloseFinished() This signal is emitted when a delayed close is finished. If you call close() and there is buffered output data to be written, Q3Socket goes into the Q3Socket::Closing state and returns immediately. It will then keep writing to the socket until all the data has been written. Then, the delayedCloseFinished() signal is emitted. \sa close()*//*! \fn void Q3Socket::readyRead() This signal is emitted every time there is new incoming data. Bear in mind that new incoming data is only reported once; if you do not read all the data, this class buffers the data and you can read it later, but no signal is emitted unless new data arrives. A good practice is to read all data in the slot connected to this signal unless you are sure that you need to receive more data to be able to process it. \sa readBlock(), readLine(), bytesAvailable()*//*! \fn void Q3Socket::bytesWritten( int nbytes ) This signal is emitted when data has been written to the network. The \a nbytes parameter specifies how many bytes were written. The bytesToWrite() function is often used in the same context; it indicates how many buffered bytes there are left to write. \sa writeBlock(), bytesToWrite()*//*! Opens the socket using the specified QIODevice file mode \a m. This function is called automatically when needed and you should not call it yourself. \sa close()*/bool Q3Socket::open( OpenMode m ){ if ( isOpen() ) {#if defined(QT_CHECK_STATE) qWarning( "Q3Socket::open: Already open" );#endif return false; } QIODevice::setOpenMode( m & ReadWrite ); return true;}/*! \fn bool Q3Socket::open(int m) \overload*//*! Closes the socket. The read buffer is cleared. If the output buffer is empty, the state is set to \c Q3Socket::Idle and the connection is terminated immediately. If the output buffer still contains data to be written, Q3Socket goes into the Q3Socket::Closing state and the rest of the data will be written. When all of the outgoing data have been written, the state is set to Q3Socket::Idle and the connection is terminated. At this point, the delayedCloseFinished() signal is emitted. If you don't want that the data of the output buffer is written, call clearPendingData() before you call close(). \sa state(), bytesToWrite() clearPendingData()*/void Q3Socket::close(){ if ( !isOpen() || d->state == Idle ) // already closed return; if ( d->state == Closing ) return; if ( !d->rsn || !d->wsn ) return;#if defined(Q3SOCKET_DEBUG) qDebug( "Q3Socket (%s): close socket", name() );#endif if ( d->socket && d->wsize ) { // there's data to be written d->state = Closing; if ( d->rsn ) d->rsn->setEnabled( false ); if ( d->wsn ) d->wsn->setEnabled( true ); d->rba.clear(); // clear incoming data return; } resetStatus(); setOpenMode(NotOpen); d->close(); d->state = Idle;}/*! This function consumes \a nbytes bytes of data from the write buffer.*/bool Q3Socket::consumeWriteBuf( Q_ULONG nbytes ){ if ( nbytes <= 0 || (qint64)nbytes > d->wsize ) return false;#if defined(Q3SOCKET_DEBUG) qDebug( "Q3Socket (%s): skipWriteBuf %d bytes", name(), (int)nbytes );#endif d->wsize -= nbytes; for ( ;; ) { QByteArray *a = d->wba.first(); if ( (qint64)(d->windex + nbytes) >= a->size() ) { nbytes -= a->size() - d->windex; d->wba.remove(); d->windex = 0; if ( nbytes == 0 ) break; } else { d->windex += nbytes; break; } } return true;}/*! Implementation of the abstract virtual QIODevice::flush() function. This function always returns true.*/bool Q3Socket::flush(){ if ( !d->socket ) return true; bool osBufferFull = false; int consumed = 0; while ( !osBufferFull && d->state >= Connecting && d->wsize > 0 ) {#if defined(Q3SOCKET_DEBUG) qDebug( "Q3Socket (%s): flush: Write data to the socket", name() );#endif QByteArray *a = d->wba.first(); int nwritten; int i = 0; if ( (int)a->size() - d->windex < 1460 ) { // Concatenate many smaller blocks. the first may be // partial, but each subsequent block is copied entirely // or not at all. the sizes here are picked so that we // generally won't trigger nagle's algorithm in the tcp // implementation: we concatenate if we'd otherwise send // less than PMTU bytes (we assume PMTU is 1460 bytes), // and concatenate up to the largest payload TCP/IP can // carry. with these precautions, nagle's algorithm // should apply only when really appropriate. QByteArray out( 65536 ); int j = d->windex; int s = a->size() - j; while ( a && i+s < (int)out.size() ) { memcpy( out.data()+i, a->data()+j, s ); j = 0; i += s; a = d->wba.next(); s = a ? a->size() : 0; } nwritten = d->socket->write( out.data(), i ); if ( d->wsn ) d->wsn->setEnabled( false ); // the QSocketNotifier documentation says so } else { // Big block, write it immediately i = a->size() - d->windex; nwritten = d->socket->write( a->data() + d->windex, i ); if ( d->wsn ) d->wsn->setEnabled( false ); // the QSocketNotifier documentation says so } if ( nwritten > 0 ) { if ( consumeWriteBuf( nwritten ) ) consumed += nwritten; } if ( nwritten < i ) osBufferFull = true; } if ( consumed > 0 ) {#if defined(Q3SOCKET_DEBUG) qDebug( "Q3Socket (%s): flush: wrote %d bytes, %d left", name(), consumed, (int)d->wsize );#endif emit bytesWritten( consumed ); } if ( d->state == Closing && d->wsize == 0 ) {#if defined(Q3SOCKET_DEBUG) qDebug( "Q3Socket (%s): flush: Delayed close done. Terminating.", name() );#endif resetStatus(); setOpenMode(NotOpen); d->close(); d->state = Idle; emit delayedCloseFinished(); return true; } if ( !d->socket->isOpen() ) { d->connectionClosed(); emit connectionClosed(); return true; } if ( d->wsn ) d->wsn->setEnabled( d->wsize > 0 ); // write if there's data return true;}/*! Returns the number of incoming bytes that can be read right now (like bytesAvailable()).*/QIODevice::Offset Q3Socket::size() const{ return (Offset)bytesAvailable();}/*! Returns the current read index. Since Q3Socket is a sequential device, the current read index is always zero.*/QIODevice::Offset Q3Socket::at() const{ return 0;}/*! \overload Moves the read index forward to \a index and returns true if the operation was successful; otherwise returns false. Moving the index forward means skipping incoming data.*/bool Q3Socket::at( Offset index ){ if ( index > d->rba.size() ) return false; d->rba.consumeBytes( (Q_ULONG)index, 0 ); // throw away data 0..index-1 // After we read data from our internal buffer, if we use the // setReadBufferSize() to limit our buffer, we might now be able to // read more data in our buffer. So enable the read socket notifier, // but do this only if we are not in a slot connected to the // readyRead() signal since this might cause a bad recursive behavior. // We can test for this condition by looking at the // sn_read_alreadyCalled flag. if ( d->rsn && Q3SocketPrivate::sn_read_alreadyCalled.findRef(this) == -1 ) d->rsn->setEnabled( true ); return true;}/*! Returns true if there is no more data to read; otherwise returns false.*/bool Q3Socket::atEnd() const{ if ( d->socket == 0 ) return true; Q3Socket * that = (Q3Socket *)this; if ( that->d->socket->bytesAvailable() ) // a little slow, perhaps... that->sn_read(); return that->d->rba.size() == 0;}/*! Returns the number of incoming bytes that can be read, i.e. the size of the input buffer. Equivalent to size(). \sa bytesToWrite()*/qint64 Q3Socket::bytesAvailable() const{ if ( d->socket == 0 ) return 0; Q3Socket * that = (Q3Socket *)this; if ( that->d->socket->bytesAvailable() ) // a little slow, perhaps... (void)that->sn_read(); return that->d->rba.size() + QIODevice::bytesAvailable();}/*! Wait up to \a msecs milliseconds for more data to be available. If \a msecs is -1 the call will block indefinitely. Returns the number of bytes available. If \a timeout is non-null and no error occurred (i.e. it does not return -1): this function sets *\a timeout to true, if the reason for returning was that the timeout was reached; otherwise it sets *\a timeout to false. This is useful to find out if the peer closed the connection. \warning This is a blocking call and should be avoided in event driven applications. \sa bytesAvailable()*/Q_ULONG Q3Socket::waitForMore( int msecs, bool *timeout ) const{ if ( d->socket == 0 ) return 0; Q3Socket * that = (Q3Socket *)this; if ( that->d->socket->waitForMore( msecs, timeout ) > 0 ) (void)that->sn_read( true ); return that->d->rba.size();}/*! \overload*/Q_ULONG Q3Socket::waitForMore( int msecs ) const{ return waitForMore( msecs, 0 );}/*! Returns the number of bytes that are waiting to be written, i.e. the size of the output buffer. \sa bytesAvailable() clearPendingData()*/qint64 Q3Socket::bytesToWrite() const{ return d->wsize;}/*! Deletes the data that is waiting to be written. This is useful if you want to close the socket without waiting for all the data to be written. \sa bytesToWrite() close() delayedCloseFinished()*/void Q3Socket::clearPendingData(){ d->wba.clear(); d->windex = d->wsize = 0;}/*! Reads \a maxlen bytes from the socket into \a data and returns the number of bytes read. Returns -1 if an error occurred.*/qint64 Q3Socket::readData( char *data, qint64 maxlen ){ if ( data == 0 && maxlen != 0 ) {#if defined(QT_CHECK_NULL) qWarning( "Q3Socket::readBlock: Null pointer error" );#endif return -1; } if ( !isOpen() ) {#if defined(QT_CHECK_STATE) qWarning( "Q3Socket::readBlock: Socket is not open" );#endif return -1; } if ( maxlen >= d->rba.size() ) maxlen = d->rba.size();#if defined(Q3SOCKET_DEBUG) qDebug( "Q3Socket (%s): readBlock %d bytes", name(), (int)maxlen );#endif d->rba.consumeBytes( maxlen, data ); // After we read data from our internal buffer, if we use the // setReadBufferSize() to limit our buffer, we might now be able to // read more data in our buffer. So enable the read socket notifier, // but do this only if we are not in a slot connected to the // readyRead() signal since this might cause a bad recursive behavior. // We can test for this condition by looking at the // sn_read_alreadyCalled flag. if ( d->rsn && Q3SocketPrivate::sn_read_alreadyCalled.findRef(this) == -1 ) d->rsn->setEnabled( true ); return maxlen;}/*! Writes \a len bytes to the socket from \a data and returns the number of bytes written. Returns -1 if an error occurred.*/qint64 Q3Socket::writeData( const char *data, qint64 len ){#if defined(QT_CHECK_NULL) if ( data == 0 && len != 0 ) { qWarning( "Q3Socket::writeBlock: Null pointer error" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -