Comment faire proprement reconnecter un boost::socket à la suite d'une déconnexion?

Mon application cliente utilise un boost::asio::ip::tcp::socket pour se connecter à un serveur distant.
Si l'application perd la connexion à ce serveur (en raison par exemple du serveur en panne ou fermeture), j'aimerais qu'elle pour tenter de se re-connecter à intervalles réguliers jusqu'à ce qu'il réussisse.

Que dois-je faire sur le côté client à proprement gérer une déconnexion, tidy up et alors à plusieurs reprises tentative de se reconnecte?

Actuellement bits intéressants de mon code ressemble à quelque chose comme ça.

Je connect comme ceci:

bool MyClient::myconnect()
{
    bool isConnected = false;

    //Attempt connection
    socket.connect(server_endpoint, errorcode);

    if (errorcode)
    {
        cerr << "Connection failed: " << errorcode.message() << endl;
        mydisconnect();
    }
    else
    {
        isConnected = true;

        //Connected so setup async read for an incoming message.
        startReadMessage();

        //And start the io_service_thread
        io_service_thread = new boost::thread(
            boost::bind(&MyClient::runIOService, this, boost::ref(io_service)));
    }
    return (isConnected)
}

Où la runIOServer() méthode est juste:

void MyClient::runIOService(boost::asio::io_service& io_service)
{
    size_t executedCount = io_service.run();
    cout << "io_service: " << executedCount << " handlers executed." << endl;
    io_service.reset();
}

Et si l'un des async lire gestionnaires de renvoyer un message d'erreur, puis ils ont juste appeler cette disconnect méthode:

void MyClient::mydisconnect(void)
{
    boost::system::error_code errorcode;

    if (socket.is_open())
    {
        //Boost documentation recommends calling shutdown first
        //for "graceful" closing of socket.
        socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorcode);
        if (errorcode)
        {
            cerr << "socket.shutdown error: " << errorcode.message() << endl;
        }

        socket.close(errorcode);
        if (errorcode)
        {
            cerr << "socket.close error: " << errorcode.message() << endl;
        }    

        //Notify the observer we have disconnected
        myObserver->disconnected();            
    }

..qui tente de mettre gracieusement débranchez puis en informe l'observateur, ce qui permettra de lancer l'appel connect() à cinq secondes jusqu'à ce qu'il obtient reconnecté.

Est-il autre chose que je dois faire?

Actuellement, ce n' semblent de travail. Si je tue le serveur auquel il est connecté à je obtenir attendus "End of file" erreur lors de ma lecture des gestionnaires et mydisconnect() est appelée sans aucun problème.

Mais quand il tente alors de se re-connecter et échoue je voir rapport "socket.shutdown error: Invalid argument". Est-ce juste parce que je suis tenter de fermer un socket qui n'est pas en lecture/écritures en attente sur elle? Ou est-il quelque chose de plus?

  • Quel est votre justification de l'appel de l'arrêt, si vous avez déjà détecté l'autre extrémité de la connexion fermée?
  • N'est-ce pas recommandé? Je pensais que il peut y avoir des opérations en cours sur le socket qui doivent être annulées avec un shutdown(). J'ai surtout tout faire pour la simplicité: le même mydisconnect() méthode est appelée si je veux déconnecter normalement, ou si l'une des opérations asynchrones retourner une erreur.
  • Je ne sais pas si c'est recommandé ou pas. Où serait l'attente de données ou d'opérations? L'autre extrémité de la connexion n'est pas là.
  • Il n'est pas nécessaire. Il est recommandé dans un largement méconnu l'article MSDN dont le but est de vous montrer comment réaliser synchronisée se ferme par deux pairs, mais dans ce cas vous ne devez arrêt pour la sortie. close() est tout ce qui est nécessaire. Des données sont encore en vol est toujours livré.
InformationsquelleAutor GrahamS | 2010-06-17