2016-02-12 63 views
0

我有什麼似乎沒有問題,但我不明白的錯誤。基本上,我一直在嘗試處理「優雅地」關閉兩端的tcp套接字的代碼。在我的程序結束時,雙方都關閉了插座,然後關閉它們。在快速重新啓動時,我試圖解決這個問題,因爲插座在雙方都徘徊不前而發生的更嚴重的崩潰問題不再發生。關機/然後關閉似乎在這方面工作。Asio:「地址已在使用」綁定,但我仍然可以連接

但是,我仍然得到「地址已被使用」,這通常會導致我無法連接。現在,我可以在發生錯誤後連接。我讀了很多關於graceful shutdownreuse address等的主題。我想我的問題是,如果套接字在綁定時發生錯誤(「地址已被使用」),在成功打開後,它是否可能能夠連接到端點?換句話說,如果地址實際上已經在使用,連接是如何進行的?另外,值得注意的是,重用地址在這種情況下不起作用。因爲我使用相同的套接字設置,本地/遠程地址和IP。

+0

你確實老工藝真的殺了你連接到舊的,而不是新的,其提供錯誤? –

+0

如果這是在linux/os x/freebsd上,你可以試試netstat -na | grep your-port-number,看看這個過程是否還在。 – kometen

+0

感謝您的意見。 @Joachim,我很確定這個過程已經死了。我已經徹底關閉了窗口,並確實打開關閉和關閉和套接字析構函數。如果操作系統以某種方式允許一個新進程控制舊的進程套接字,那將是相當驚人的。看起來很不安全。 kometen,我會給它一個肯定的嘗試 –

回答

1

未能bind()套接字到地址不會使底層套接字無效。因此,connect()操作將繼續使用未綁定的套接字,並推遲到內核綁定到本地端點。


下面是一個完整的例子demonstrating此行爲:

#include <boost/asio.hpp> 
#include <boost/bind.hpp> 

// This example is not interested in all handlers, so provide a noop function 
// that will be passed to bind to meet the handler concept requirements. 
void noop() {} 

int main() 
{ 
    using boost::asio::ip::tcp; 

    // Create all I/O objects. 
    boost::asio::io_service io_service; 
    tcp::acceptor acceptor(io_service, {tcp::v4(), 0}); 
    tcp::socket server(io_service, tcp::v4()); 

    // Open socket1, binding to a random port. 
    tcp::socket socket1(io_service, {boost::asio::ip::address_v4::any(), 0}); 
    tcp::socket socket2(io_service); // non-open 

    // Explicitly open client2, which will bind it to the any address. 
    boost::system::error_code error; 
    socket2.open(tcp::v4(), error); 
    assert(!error); 
    assert(socket2.local_endpoint().port() == 0); 

    // Attempt to bind socket2 to socket1's address will fail with 
    // an already in use error, leaving socket2 bound to the any endpoint. 
    // (e.g. a failed bind does not have side effects on the socket) 
    socket2.bind(socket1.local_endpoint(), error); 
    assert(error == boost::asio::error::address_in_use); 
    assert(socket2.local_endpoint().port() == 0); 

    // Connect will defer to the kernel to bind the socket. 
    acceptor.async_accept(server, boost::bind(&noop)); 
    socket2.async_connect(acceptor.local_endpoint(), 
    [&error](const boost::system::error_code& ec) { error = ec; }); 
    io_service.run(); 
    io_service.reset(); 
    assert(!error); 
    assert(socket2.local_endpoint().port() != 0); 
} 
+0

非常感謝解釋。 –

相關問題