Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Fonctions  · 

A simple NNTP implementation

This example shows how to implement your own QNetworkProtocol. The protocol that was chosen for this example is NTTP. Please note that this implementation is very simple since it is designed to be an example. It should not be used as a real NNTP implemention.


Header file (nntp.h):

/****************************************************************************
** $Id: $
**
** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
**
** This file is part of an example program for Qt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#ifndef NNTP_H
#define NNTP_H

#include <qsocket.h>
#include <qnetworkprotocol.h>

class Nntp : public QNetworkProtocol
{
    Q_OBJECT

public:
    Nntp();
    virtual ~Nntp();
    virtual int supportedOperations() const;

protected:
    virtual void operationListChildren( QNetworkOperation *op );
    virtual void operationGet( QNetworkOperation *op );

    QSocket *commandSocket;
    bool connectionReady;
    bool readGroups;
    bool readArticle;

private:
    bool checkConnection( QNetworkOperation *op );
    void close();
    void parseGroups();
    void parseArticle();

protected slots:
    void hostFound();
    void connected();
    void closed();
    void readyRead();
    void error( int );

};

#endif


Implementation (nntp.cpp):

/****************************************************************************
** $Id: $
**
** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
**
** This file is part of an example program for Qt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#include "nntp.h"
#include <qurlinfo.h>
#include <stdlib.h>
#include <qurloperator.h>
#include <qstringlist.h>
#include <qregexp.h>

Nntp::Nntp()
    : QNetworkProtocol(), connectionReady( FALSE ),
      readGroups( FALSE ), readArticle( FALSE )
{
    // create the command socket and connect to its signals
    commandSocket = new QSocket( this );
    connect( commandSocket, SIGNAL( hostFound() ),
             this, SLOT( hostFound() ) );
    connect( commandSocket, SIGNAL( connected() ),
             this, SLOT( connected() ) );
    connect( commandSocket, SIGNAL( connectionClosed() ),
             this, SLOT( closed() ) );
    connect( commandSocket, SIGNAL( readyRead() ),
             this, SLOT( readyRead() ) );
    connect( commandSocket, SIGNAL( error( int ) ),
             this, SLOT( error( int ) ) );
}

Nntp::~Nntp()
{
    close();
    delete commandSocket;
}

void Nntp::operationListChildren( QNetworkOperation * )
{
    // create a command
    QString path = url()->path(), cmd;
    if ( path.isEmpty() || path == "/" ) {
        // if the path is empty or we are in the root dir,
        // we want to read the list of available newsgroups
        cmd = "list newsgroups\r\n";
    } else if ( url()->isDir() ) {
        // if the path is a directory (in our case a news group)
        // we want to list the articles of this group
        path = path.replace( "/", "" );
        cmd = "listgroup " + path + "\r\n";
    } else
        return;

    // write the command to the socket
    commandSocket->writeBlock( cmd.latin1(), cmd.length() );
    readGroups = TRUE;
}

void Nntp::operationGet( QNetworkOperation *op )
{
    // get the dirPath of the URL (this is our news group)
    // and the filename (which is the article we want to read)
    QUrl u( op->arg( 0 ) );
    QString dirPath = u.dirPath(), file = u.fileName();
    dirPath = dirPath.replace( "/", "" );

    // go to the group in which the article is
    QString cmd;
    cmd = "group " + dirPath + "\r\n";
    commandSocket->writeBlock( cmd.latin1(), cmd.length() );

    // read the head of the article
    cmd = "article " + file + "\r\n";
    commandSocket->writeBlock( cmd.latin1(), cmd.length() );
    readArticle = TRUE;
}

bool Nntp::checkConnection( QNetworkOperation * )
{
    // we are connected, return TRUE
    if ( commandSocket->isOpen() && connectionReady )
        return TRUE;

    // seems that there is no chance to connect
    if ( commandSocket->isOpen() )
        return FALSE;

    // don't call connectToHost() if we are already trying to connect
    if ( commandSocket->state() == QSocket::Connecting )
        return FALSE;

    // start connecting
    connectionReady = FALSE;
    commandSocket->connectToHost( url()->host(),
                                  url()->port() != -1 ? url()->port() : 119 );
    return FALSE;
}

void Nntp::close()
{
    // close the command socket
    if ( commandSocket->isOpen() ) {
        commandSocket->writeBlock( "quit\r\n", strlen( "quit\r\n" ) );
        commandSocket->close();
    }
}

int Nntp::supportedOperations() const
{
    // we only support listing children and getting data
    return OpListChildren | OpGet;
}

void Nntp::hostFound()
{
    if ( url() )
        emit connectionStateChanged( ConHostFound, tr( "Host %1 found" ).arg( url()->host() ) );
    else
        emit connectionStateChanged( ConHostFound, tr( "Host found" ) );
}

void Nntp::connected()
{
    if ( url() )
        emit connectionStateChanged( ConConnected, tr( "Connected to host %1" ).arg( url()->host() ) );
    else
        emit connectionStateChanged( ConConnected, tr( "Connected to host" ) );
}

void Nntp::closed()
{
    if ( url() )
        emit connectionStateChanged( ConClosed, tr( "Connection to %1 closed" ).arg( url()->host() ) );
    else
        emit connectionStateChanged( ConClosed, tr( "Connection closed" ) );
}

void Nntp::readyRead()
{
    // new data arrived on the command socket

    // of we should read the list of available groups, let's do so
    if ( readGroups ) {
        parseGroups();
        return;
    }

    // of we should read an article, let's do so
    if ( readArticle ) {
        parseArticle();
        return;
    }

    // read the new data from the socket
    QCString s;
    s.resize( commandSocket->bytesAvailable() );
    commandSocket->readBlock( s.data(), commandSocket->bytesAvailable() );

    if ( !url() )
        return;

    // of the code of the server response was 200, we know that the
    // server is ready to get commands from us now
    if ( s.left( 3 ) == "200" )
        connectionReady = TRUE;
}

void Nntp::parseGroups()
{
    if ( !commandSocket->canReadLine() )
        return;

    // read one line after the other
    while ( commandSocket->canReadLine() ) {
        QString s = commandSocket->readLine();

        // if the  line starts with a dot, all groups or articles have been listed,
        // so we finished processing the listChildren() command
        if ( s[ 0 ] == '.' ) {
            readGroups = FALSE;
            operationInProgress()->setState( StDone );
            emit finished( operationInProgress() );
            return;
        }

        // if the code of the server response is 215 or 211
        // the next line will be the first group or article (depending on what we read).
        // So let others know that we start reading now...
        if ( s.left( 3 ) == "215" || s.left( 3 ) == "211" ) {
            operationInProgress()->setState( StInProgress );
            emit start( operationInProgress() );
            continue;
        }

        // parse the line and create a QUrlInfo object
        // which describes the child (group or article)
        bool tab = s.find( '\t' ) != -1;
        QString group = s.mid( 0, s.find( tab ? '\t' : ' ' ) );
        QUrlInfo inf;
        inf.setName( group );
        QString path = url()->path();
        inf.setDir( path.isEmpty() || path == "/" );
        inf.setSymLink( FALSE );
        inf.setFile( !inf.isDir() );
        inf.setWritable( FALSE );
        inf.setReadable( TRUE );

        // let others know about our new child
        emit newChild( inf, operationInProgress() );
    }

}

void Nntp::parseArticle()
{
    if ( !commandSocket->canReadLine() )
        return;

    // read an article one line after the other
    while ( commandSocket->canReadLine() ) {
        QString s = commandSocket->readLine();

        // if the  line starts with a dot, we finished reading something
        if ( s[ 0 ] == '.' ) {
            readArticle = FALSE;
            operationInProgress()->setState( StDone );
            emit finished( operationInProgress() );
            return;
        }

        if ( s.right( 1 ) == "\n" )
            s.remove( s.length() - 1, 1 );

        // emit the new data of the article which we read
        emit data( QCString( s.ascii() ), operationInProgress() );
    }
}

void Nntp::error( int code )
{
    if ( code == QSocket::ErrHostNotFound ||
         code == QSocket::ErrConnectionRefused ) {
        // this signal is called if connecting to the server failed
        if ( operationInProgress() ) {
            QString msg = tr( "Host not found or couldn't connect to: \n" + url()->host() );
            operationInProgress()->setState( StFailed );
            operationInProgress()->setProtocolDetail( msg );
            operationInProgress()->setErrorCode( (int)ErrHostNotFound );
            clearOperationQueue();
            emit finished( operationInProgress() );
        }
    }
}

See also Network Examples.

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année
  1. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 85
  2. Apercevoir la troisième dimension ou l'utilisation multithreadée d'OpenGL dans Qt, un article des Qt Quarterly traduit par Guillaume Belz 0
  3. Les développeurs ignorent-ils trop les failles découvertes dans leur code ? Prenez-vous en compte les remarques des autres ? 17
  4. BlackBerry 10 : premières images du prochain OS de RIM qui devrait intégrer des widgets et des tuiles inspirées de Windows Phone 0
  5. Pourquoi les programmeurs sont-ils moins payés que les gestionnaires de programmes ? Manquent-ils de pouvoir de négociation ? 19
  6. Quelles nouveautés de C++11 Visual C++ doit-il rapidement intégrer ? Donnez-nous votre avis 10
  7. Adieu qmake, bienvenue qbs : Qt Building Suite, un outil déclaratif et extensible pour la compilation de projets Qt 17
Page suivante

Le blog Digia au hasard

Logo

Créer des applications avec un style Metro avec Qt, exemples en QML et C++, un article de Digia Qt traduit par Thibaut Cuvelier

Le blog Digia est l'endroit privilégié pour la communication sur l'édition commerciale de Qt, où des réponses publiques sont apportées aux questions les plus posées au support. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 3.2
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web