2016-06-14 5 views
0

Meine C++ library macht TCP-Verbindung mit einer Liste der Verwendung von boost :: asio_connector_async Das Problem ist, dass, wenn einer der Streams aus irgendeinem Grund geschlossen ist, keine Informationen von Boost zu meiner Bibliothek in Bezug auf die gleiche gesendet wird. Daher kann meine Bibliothek nie erkennen, welche Streams geschlossen und welche noch offen sind. Meine Bibliothek enthält ein Objekt der Klasse boost :: asio_connector_async (mit Namen Stecker) und stellt eine Verbindung zum Host-Port auf diese Weise:Wie erkenne ich, ob ein bestimmter TCP-Stream, der über boost :: asio_stream_async verbunden ist, geschlossen ist?

connector.async_connect(hostname.c_str(), qport.c_str(),   boost::bind(bc::asio_bind_sock_chan<pubsub_channel,pubsub_channel::text_marshaler_registry>(),boost::ref(chan), boost::ref(mar_reg), hostname, qport, channel_logger, _1, _2, _3)); 

Wenn ein bestimmte <host,port> Strom geschlossen ist, wird die Funktion boost::asio_connector_async::on_stream_closed aufgerufen intern aus der Datei asio_stream_async.hpp

void on_stream_closed(void * sp, const std::string & host, const std::string port) { 
     boost::channel::logger_stream(logger_) << "boost::channel::asio_connector_async::on_stream_closed - " << host << ":" << port << ": stream 0x" << sp << " closed"; 
     } 

ich meine Bibliothek boost::asio_connector_async::on_stream_closed so anhängen möchten, dass, wenn diese spezielle Funktion aufgerufen wird, wird eine Funktion in meiner Bibliothek auch so aufgerufen, dass meine Bibliothek bewusst ist, welche bestimmte Strom ist geschlossen ed und dann sollte versuchen, wieder mit diesem Stream Bitte schlagen Sie vor, wie kann ich das gleiche erreichen? Ich kann mir sowieso nicht vorstellen, dies zu erreichen, ohne die Boost-Bibliothek zu ändern (was ich nicht tun soll) Wenn es eine andere Möglichkeit gibt, geschlossene Verbindungen zu erkennen, bitte schlage mir auch diese vor.

Ich bin neu in dieser Art von Netzwerk-Programmierung, benötigen daher Hilfe mit dem gleichen. Vielen Dank im Voraus

Antwort

0

Client-Verbindungen müssen in Ihrem handle_read Rückruf (oder welchen Namen auch immer Sie angegeben haben) behandelt werden.

Der Async-Lese-Callback wird mit 0 Bytes aus dem Stream gelesen. Oder Sie können den Systemfehlercode überprüfen als auch für asio::error::connection_reset oder asio::error::eof oder einfach bytes_read == 0

Ein Beispiel (aus Asio Beispielen: chat_client.cpp) (Ich würde empfehlen, wie auch andere erwähnten Tests zu tun.)

asio::async_connect(socket_, endpoints, 
     [this](std::error_code ec, tcp::endpoint) 
     { 
      if (!ec) 
      { 
      do_read_header(); 
      } 
     //ATTN: This is where you should handle failed socket connection 
     }); 

void do_read_header() 
    { 
    asio::async_read(socket_, 
     asio::buffer(read_msg_.data(), chat_message::header_length), 
     [this](std::error_code ec, std::size_t /*length*/) 
     { 
      if (!ec && read_msg_.decode_header()) 
      { 
      do_read_body(); 
      } 
      else 
      { 
      socket_.close(); 
      } 
     }); 
    } 

Suchen Sie nach dem ATTN Kommentar in async_connect Handler.

+0

Ich glaube nicht, Boost/channel/streams/asio_connector_async.hpp :: async_conect nimmt ein "Fehler" -Argument. Leere async_connect (std :: string Host, std :: string-Port, sock_conn_handler HNDL) Mein Code direkt async_connect ruft ein Objekt von asio_connector_sync –

+0

Mein Grundanliegen besteht darin, die Trennung Informationen an die Client-Bibliothek zu senden. Boost-Bibliothek erkennt die Trennung, wenn der Socket geschlossen ist, aber diese Information wird nicht mit der Client-Bibliothek kommuniziert. –

+0

@ShubhiAgarwal Es ist Ihr Handler, der 'asio :: error' nehmen sollte, nicht async_connect. In deinem Fall 'sock_conn_handler'. Kannst du mir die Signatur der Funktion 'sock_conn_handler' nennen? – Arunmu

0

Jeder von asio durchgeführte Anruf wird mit einem Fehler beendet, wenn ein Verbindungsfehler festgestellt wird.

Das bedeutet jedoch nicht, dass das Remote-Ende erreichbar bleibt. Der TCP-Sendevorgang wird abgeschlossen, sobald die Daten in die Kernelwarteschlange eingereiht werden. Die Erkennung von Fehlern kann lange dauern, bis sie erkannt werden.

Wenn die Verbindungstreue wichtig ist, müssen Sie eine Echoanforderung in Ihrem Protokoll der Sitzungsschicht entwerfen.

+0

Gibt es einen einfacheren Weg, dies zu tun, ohne auf Protokollebene zu ändern? –

+1

@ShubhiAgarwal Dies würde nur passieren, wenn der Endpunkt kein 'RST'-TCP-Paket senden kann. Normalerweise, wenn der Endpoint-Server-Computer abstürzt oder plötzlich ausgeschaltet wird oder aus irgendeinem anderen Grund. Sie können stattdessen 'asio :: socket_base :: keep_alive' verwenden, das Testpakete nach jedem konfigurierbaren Timeout sendet. Wenn es eine defekte Pipe erkennt, wird der Lese-Handler erneut aufgerufen, und zwar mit der Fehlermenge, die ich in meiner Antwort erwähnt habe. – Arunmu

+0

Der Socket wird ebenfalls fehlerhaft, wenn die lokale Sicherungsschicht getrennt wird (Ethernetkabel herausgezogen). Worüber Sie nicht informiert werden, ist, ob das Remote-Ethernet-Kabel herausgezogen wird oder ob ein Intermediate-Router ausfällt. – doron