0

deadline_timer接続タイムアウトとして aを使用して、boost asio を使用して 3 つの TCP ソケットに非同期的に接続するプログラムがあります。Windowsでは、すべてが期待どおりに機能します。接続は 5 秒後にタイムアウトします。ただし、Unix (WSL 上の Ubuntu、Linux Mint VM、macOS) では、connectDeadline は起動しません。async_connect 操作は永久に実行されます。これが機能しないのはなぜですか? また、これを Unix でも機能させるにはどうすればよいですか?

コード: 注: connect はメイン スレッド (GUI スレッドでもあります) から呼び出されます。

#include "NetManager.h"

NetManager::NetManager(NetManagerListener& listener) :  listener(listener),
connectDeadline(io),
                                                        socket1(io),
                                                        socket2(io),
                                                        socket3(io),
                                                        asioThread(&NetManager::handleAsioOperations, this){

}
NetManager::~NetManager() {
    running = false;
    io.stop();
    asioThread.join();
}

void NetManager::connect(){
    connectCounter = 0;
    hasHandledConnectError = false;
    socket1.async_connect(
            tcp::endpoint(boost::asio::ip::address::from_string(IP_STRING), PORT_1),
            boost::bind(&NetManager::handleConnect, this, _1));
    socket2.async_connect(
            tcp::endpoint(boost::asio::ip::address::from_string(IP_STRING), PORT_2),
            boost::bind(&NetManager::handleConnect, this, _1));
    socket3.async_connect(
            tcp::endpoint(boost::asio::ip::address::from_string(IP_STRING), PORT_3),
            boost::bind(&NetManager::handleConnect, this, _1));
    connectDeadline.expires_from_now(boost::posix_time::seconds(CONNECT_TIMEOUT));
    connectDeadline.async_wait(boost::bind(&NetManager::handleConnectTimeout, this, _1));
}

void NetManager::disconnect(){
    //NOTE: Close also cancels incomplete async operations
    socket1.close();
    socket2.close();
    socket3.close();
}

////////////////////////////////////////////////////////////////////////
/// ASIO Handlers
////////////////////////////////////////////////////////////////////////
void NetManager::handleAsioOperations(){
    while(running){
        io.run(); // Run any async operations
    }
}

void NetManager::handleConnect(const boost::system::error_code &ec){
    // When connections are canceled the handler is called with operation_aborted. No need to respond to that.
    if(ec && ec != boost::asio::error::operation_aborted && !hasHandledConnectError){
        hasHandledConnectError = true; // Likely to be 3 repeated errors. Make sure to only handle the first one
        cerr << "Connect Failed: " << ec.message() << endl;
        connectDeadline.cancel(); // Don't fire the timeout
        disconnect(); // Disconnect any already connected sockets
        connectedToRobot = false;
        listener.onConnect(false);
    }else if (!ec){
        connectCounter++;
    }

    if(connectCounter == 3){
        cout << "Successful connect" << endl;
        connectDeadline.cancel(); // Don't fire the timeout
        connectedToRobot = true;
        listener.onConnect(true);
    }
}

void NetManager::handleConnectTimeout(const boost::system::error_code &ec){
    if(ec != boost::asio::error::operation_aborted){
        cerr << "Connect timed out." << endl;
        disconnect(); // Disconnect any already connected sockets
        connectedToRobot = false;
        listener.onConnect(false);
    }
}

編集:

紛らわしいことに、これは Unix OS では問題なく動作します。

#include <boost/asio.hpp>                                                                                                                    
#include <boost/asio/deadline_timer.hpp>                                                                                                     
#include <iostream>                                                                                                                          
#include <thread>                                                                                                                            

using namespace boost::asio;                                                                                                                 
using namespace boost::asio::ip;                                                                                                             

int main(){                                                                                                                                  
        io_service io;                                                                                                                       
        deadline_timer timer1(io);                                                                                                           
        tcp::socket sock(io);                                                                                                                

        timer1.expires_from_now(boost::posix_time::seconds(3));                                                                              
        sock.async_connect(tcp::endpoint(boost::asio::ip::address::from_string("10.50.30.1"), 8090), [](const boost::system::error_code &ec){
                std::cout << "SocketError: " << ec.message() << std::endl;                                                                   
        });                                                                                                                                  
        timer1.async_wait([&](const boost::system::error_code &ec){                                                                          
                std::cout << "First timer" << std::endl;                                                                                     
                sock.close();                                                                                                                
        });                                                                                                                                  
        std::thread worker([&](){                                                                                                            
                while(true){                                                                                                                 
                        io.run();                                                                                                            
                }                                                                                                                            
        });                                                                                                                                  
        worker.detach();                                                                                                                     
        while(true){} // Simulate the unavailable main (GUI) thread                                                                          
}  

出力:

First timer
SocketError: Operation canceled
4

2 に答える 2