2016-06-24 15 views
0

Ich habe einen TCP Server, der neue Verbindungen behandelt, wenn es eine neue Verbindung gibt, werden zwei Threads erstellt (std::thread, getrennt).boost :: asio schreiben: Gebrochenes Rohr

void Gateway::startServer(boost::asio::io_service& io_service, unsigned short port) { 

    tcp::acceptor TCPAcceptor(io_service, tcp::endpoint(tcp::v4(), port)); 

    bool UARTToWiFiGatewayStarted = false; 

    for (;;) { std::cout << "\nstartServer()\n"; 

     auto socket(std::shared_ptr<tcp::socket>(new tcp::socket(io_service))); 

     /*! 
     * Accept a new connected WiFi client. 
     */ 
     TCPAcceptor.accept(*socket); 

     socket->set_option(tcp::no_delay(true)); 

     // This will set the boolean `Gateway::communicationSessionStatus` variable to true. 
     Gateway::enableCommunicationSession(); 

     // start one thread 
     std::thread(WiFiToUARTWorkerSession, socket, this->SpecialUARTPort, this->SpecialUARTPortBaud).detach(); 


     // start the second thread 
     std::thread(UARTToWifiWorkerSession, socket, this->UARTport, this->UARTbaud).detach(); 
    } 
} 

Der erste von zwei Arbeiter Funktionen wie folgt aussehen (hier lese ich die gemeinsame Buchse verwenden):

void Gateway::WiFiToUARTWorkerSession(std::shared_ptr<tcp::socket> socket, std::string SpecialUARTPort, unsigned int baud) { 
    std::cout << "\nEntered: WiFiToUARTWorkerSession(...)\n"; 

    std::shared_ptr<FastUARTIOHandler> uart(new FastUARTIOHandler(SpecialUARTPort, baud)); 

    try { 
     while(true == Gateway::communicationSessionStatus) { std::cout << "WiFi->UART\n"; 

      unsigned char WiFiDataBuffer[max_incoming_wifi_data_length]; 

      boost::system::error_code error; 

      /*! 
      * Read the TCP data. 
      */ 
      size_t length = socket->read_some(boost::asio::buffer(WiFiDataBuffer), error); 

      /*! 
      * Handle possible read errors. 
      */ 
      if (error == boost::asio::error::eof) { 
       // this will set the shared boolean variable from "true" to "false", causing the while loop (from the both functions and threads) to stop. 
       Gateway::disableCommunicationSession(); 
       break; // Connection closed cleanly by peer. 
      } 
      else if (error) { 
       Gateway::disableCommunicationSession(); 
       throw boost::system::system_error(error); // Some other error. 
      } 

      uart->write(WiFiDataBuffer, length); 
     } 
    } 
    catch (std::exception &exception) { 
     std::cerr << "[APP::exception] Exception in thread: " << exception.what() << std::endl; 
    } 

    std::cout << "\nExiting: WiFiToUARTWorkerSession(...)\n"; 
} 

und die zweite (hier schreibe ich die Thread-shared mit Buchse):

void Gateway::UARTToWifiWorkerSession(std::shared_ptr<tcp::socket> socket, std::string UARTport, unsigned int baud) { 
    std::cout << "\nEntered: UARTToWifiWorkerSession(...)\n"; 

    /*! 
    * Buffer used for storing the UART-incoming data. 
    */ 
    unsigned char UARTDataBuffer[max_incoming_uart_data_length]; 
    std::vector<unsigned char> outputBuffer; 

    std::shared_ptr<FastUARTIOHandler> uartHandler(new FastUARTIOHandler(UARTport, baud)); 

    while(true == Gateway::communicationSessionStatus) { std::cout << "UART->WiFi\n"; 

     /*! 
     * Read the UART-available data. 
     */ 
     auto bytesReceived = uartHandler->read(UARTDataBuffer, max_incoming_uart_data_length); 


     /*! 
     * If there was some data, send it over TCP. 
     */ 
     if(bytesReceived > 0) { 
      boost::asio::write((*socket), boost::asio::buffer(UARTDataBuffer, bytesReceived)); 

      std::cout << "\nSending data to app...\n"; 
     } 
    } 

    std::cout << "\nExited: UARTToWifiWorkerSession(...)\n"; 
} 

Zum Stoppen dieser zwei Threads ich folgendes tun: von der WiFiToUARTWorkerSession(...) Funktion, wenn die read(...) ausfällt (es gibt einen Fehler wie boost::asio::error::eof, oder irgendein anderer Fehler) Ich setze den booleschen Gateway::communicationSessionStatus Schalter (der von den beiden Funktionen (global) geteilt wird) auf false, auf diese Weise sollten die Funktionen zurückkehren, und die Threads sollten anmutig beendet werden.

Wenn ich zum ersten Mal anschließen, das funktioniert gut, aber wenn ich von dem Server bin Abklemmen der Ausführungsablauf von den WiFiToUARTWorkerSession(...) geht durch else if (error) Zustand, setzt sich die while Bedingung Variable false und dann es wirft boost::system::system_error(error) (was eigentlich Connection reset by peer bedeutet).

Dann, wenn ich versuche, wieder zu verbinden, habe ich die folgende Ausnahme, und das Programm endet:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >' 
    what(): write: Broken pipe 

Was könnte das Problem sein?

EDIT: Von dem, was ich über diesen Fehler gefunden, so scheint es, dass ich write(...) nach der Client die Verbindung trennt, sondern, wie dies möglich sein könnte?

EDIT2: Ich habe den Code noch debugged und es scheint, dass ein Thread (auf das läuft die UARTToWifiWorkerSession(...)-Funktion) wird nicht tatsächlich zu beenden (weil es eine Blockierung read(...) Funktionsaufruf bei dem die Ausführung Fluss stoppt). Auf diese Weise wird ein Thread hängen bleiben, bis einige Daten von der read(...)-Funktion empfangen werden, und wenn ich die Verbindung wieder herstelle, werden zwei weitere Threads erstellt, was einige Datenprobleme verursacht.

Kann mir jemand bestätigen, dass dies das Problem sein könnte?

+0

so ist das Problem, mit dem Klienten Verbindung mit dem Server, richtig? Und Sie haben nicht die Client-Seite des Codes geschrieben. Von was ich denke, ist das, was Sie versuchen zu machen eine Verbindung von der gleichen Buchse, ohne sie zuerst zu schließen. – Arunmu

+0

@Arunmu Ich habe den Code nicht von der Client-Seite, aber was denkst du, wäre das mit dem Client falsch? Und was meinst du damit, dass ich die gleiche Steckdose benutze?Für jede neue Verbindung gibt es einen neuen Socket. –

+0

'Wenn ich versuche, mich wieder zu verbinden..' wo passiert das? Client-Seite oder Server-Seite? – Arunmu

Antwort

0

Das eigentliche Problem war, dass die Funktion UARTToWifiWorkerSession(...) nicht wirklich Ausgang (wegen einer Blockierung read(...) Funktion, dies verursacht zwei Threads (das Aufhängen einer, und einer der letzten beiden geschaffen sind) zu write(...) (ohne Nebenläufigkeitssteuerung die gleiche Buchse verwendet wird).

die Lösung eine read(...) Timeout eingestellt war, so dass ich aus der Funktion zurück (und damit den Faden) zerstören, ohne von irgendeinem Eingang anstehen.

Verwandte Themen