简体   繁体   中英

Handling “reset by peer” scenario with boost::asio

I have a server method that waits for new incoming TCP connections, for each connection I'm creating two threads (detached) for handling various tasks.

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

This works fine for starting the communication, but the problem appears when the client disconnects and connects again (or at least tries to connect again).

When the current client disconnects, I stop the communication (by stopping the internal infinite loops from both functions, then they'll return).

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

I expect that when I reconnect the communication should work again (the MyClass::startServer(...) will create and detach again two worker threads that will do the same things.

The problem is that when I connect the second time I get:

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

From what I found about this error it seems that the server (this application) sends something via TCP to a client that was disconnected.

What I'm doing wrong?

How can I solve this problem?

  1. A read of length 0 with no error is also an indication of eof. The boost::asio::error::eof error code is normally more useful when you're checking the result of a composed operation.

  2. When this error condition is missed, the code as presented will call write on a socket which has now been shutdown. You have used the form of write which does not take a reference to an error_code . This form will throw if there is an error. There will be an error. The read has failed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM