2016-06-23 66 views
0

我有一個服務器方法,它等待新的傳入TCP連接,爲每個連接創建兩個線程(分離)以處理各種任務。使用boost :: asio處理「peer by peer」場景

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

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

     bool UARTToWiFiGatewayStarted = false; 

     for (;;) { 

      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)); 

      MyClass::enableCommunicationSession(); 

      // start one worker thread. 
      std::thread(WiFiToUARTWorkerSession, socket, this->LINport, this->LINbaud).detach(); 

      // only if this is the first connected client: 
      if(false == UARTToWiFiGatewayStarted) { 

       std::thread(UARTToWifiWorkerSession, socket, this->UARTport, this->UARTbaud).detach(); 

       UARTToWiFiGatewayStarted = true; 
      } 
     } 
    } 

這正常啓動通訊,但是當客戶端斷開連接並重新連接(或者至少再次嘗試連接)出現的問題。

當前客戶端斷開連接時,我停止通信(通過停止兩個函數的內部無限循環,然後它們將返回)。

void Gateway::WiFiToUARTWorkerSession(std::shared_ptr<tcp::socket> socket, ...) { 

     /*! 
     * various code here... 
     */ 

     try { 
      while(true == MyClass::communicationSessionStatus) { 

       /*! 
       * Buffer used for storing the UART-incoming data. 
       */ 
       unsigned char WiFiDataBuffer[max_incoming_wifi_data_length]; 

       boost::system::error_code error; 

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

       /*! 
       * Handle possible read errors. 
       */ 
       if (error == boost::asio::error::eof) { 
        break; // Connection closed cleanly by peer. 
       } 
       else if (error) { 
        // this will cause the infinite loops from the both worker functions to stop, and when they stop the functions will return. 
        MyClass::disableCommunicationSession(); 
        sleep(1); 
        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; 
     } 
    } 

我希望,當我重新連接通信應該重新工作(該MyClass::startServer(...)將創建並detach又來了兩位工作線程會做同樣的事情。

的問題是,當我連接第二次我得到:

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 

從我發現這個錯誤似乎服務器(此應用程序),通過TCP發送的東西給已斷開客戶機

我在做什麼錯了?

我該如何解決這個問題?

回答

1
  1. 長度爲0且沒有錯誤的讀取也是eof的指示。當您檢查組合操作的結果時,boost::asio::error::eof錯誤代碼通常更有用。

  2. 當這個錯誤條件被遺漏時,所提供的代碼將在已經關閉的套接字上調用write。您已經使用了不參考error_code的寫入形式。如果出現錯誤,此表單將拋出。將會出現錯誤。讀取失敗。

+0

我會解決這個問題,但我不認爲這是問題,因爲當客戶端斷開連接時,執行流經過'else if(error)'路徑。 –

+0

@MariusMarusanici更新的答案更清晰 –

+0

那麼解決方案是什麼? –