2013-02-28 105 views
2

我想在C++中使用新類來包裝boost TCP。當我直接調用boost函數時,事情就像一個魅力。然而,當閉包被封裝在類函數中時,我無法調用套接字關閉。請幫助看看下面的代碼。使用shared_ptr boost tcp socket C++

類認定中:

typedef boost::shared_ptr<tcp::socket> Socket; 
class TCPConnector{ 
public : 
    bool isConnected; 
    Socket sock; 
    string ip; 
    int port; 
    TCPConnector(string ip, int port); 

    void Close(); 
    bool Connect(); 
}; 

功能:

TCPConnector::TCPConnector(string ip,int port):ip(ip),port(port) 
{ 

} 

void TCPConnector::Close() { 
    boost::system::error_code error; 
    if (!isConnected) 
     return; 
    isConnected = false; 

    try { 

     sock->shutdown(boost::asio::ip::tcp::socket::shutdown_both, error); 
     cout << "ShutDown" << endl; 
     if (error) 
      throw boost::system::system_error(error); 
     sock->close(error); 
     if (error) 
      throw boost::system::system_error(error); 
    } catch (exception& e) { 
     cout << "#TCPConnector::Close()#" << e.what() << endl; 
    } 
} 

主要功能:

int main(int argc, char* argv[]) { 
    try { 
     TCPConnector* conn = new TCPConnector("127.0.0.1",8088); 

     for (int i = 0; i < 2; i++) { 
      boost::asio::io_service io_service; 
      tcp::resolver resolver(io_service); 
      tcp::resolver::query query(tcp::v4(), "127.0.0.1", "8088"); 
      tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); 
      conn->sock.reset(new tcp::socket(io_service)); 
      conn->sock->connect(*endpoint_iterator); 
      cout << "Connected" << endl; 
      boost::thread acceptorThread(boost::bind(receive,conn)); 
      sleep(1); 
      unsigned char msg[8] = { 0, 6, 55, 56, 55, 56, 55, 0 }; 
      boost::system::error_code error; 
      try { 

       boost::asio::write(*conn->sock, boost::asio::buffer(msg, 8), 
         boost::asio::transfer_all(), error); 
       cout << "Sent" << endl; 
       if (error) 
        throw boost::system::system_error(error); 
       conn->sock->shutdown(boost::asio::ip::tcp::socket::shutdown_both, 
         error); 
       if (error) 
        throw boost::system::system_error(error); 




       conn->sock->close(error);//close socket directly , the result is ok 
       //conn->Close();// close by calling functions, it causes problems. 





       cout << "Closed" << endl; 
       if (error) 
        throw boost::system::system_error(error); 
       io_service.stop(); 
      } catch (std::exception& e) { 
       std::cerr << "Exception in thread: " << e.what() << "\n"; 
      } 
      cout << "Sleep" << endl; 
      sleep(2); 
      cout << "Wake up" << endl; 
     } 
    } catch (std::exception& e) { 
     std::cerr << e.what() << std::endl; 
    } 
    return 0; 
} 

這些2行連鎖行業e不同的行爲。我不知道爲什麼第二個會導致問題。

conn->sock->close(error);//close socket directly , the result is ok 
conn->Close();// close by calling functions, it causes problems. 

互斥:無效的參數印在

sock->close(error); 
     if (error) 
      throw boost::system::system_error(error); 

是對於shared_ptr的相關問題?或者我錯過了一些重要的關閉套接字?

感謝您的任何建議。

+0

'io_service'應該超過'socket'。嘗試在for循環之外移動'io_service',或者在for循環結束時調用'conn-> sock.reset();'。 – Fraser 2013-02-28 03:11:41

+0

感謝您的回覆。在第一個循環中,錯誤在'conn-> Close();'之後拋出,所以程序無法繼續。或者你的意思是在'conn-> Close();'之前調用'conn-> sock.reset()'? – HenryLok 2013-02-28 03:21:04

+0

@Fraser非常感謝!在'conn-> Close();'之前添加'conn-> sock.reset();'之後,代碼就可以工作了。我可以試着解釋一下,你可以幫助評估它是否正確。由於'conn-> sock.reset(new tcp :: socket(io_service));'在'io_service.stop();'之後運行,因此'io_service'的活動時間比套接字長(在之前關閉循環)。但爲什麼這會導致互斥錯誤,爲什麼'io_service'必須比套接字壽命更長?非常感謝! – HenryLok 2013-02-28 03:29:14

回答

3

問題是io_service應該比socket長。

除了for循環的第一次迭代之外,語句conn->sock.reset(new tcp::socket(io_service));都調用了先前迭代套接字的析構函數。這個析構函數訪問先前迭代的io_service(特別是它的互斥體)的元素,該元素在那之前已被銷燬。

爲了解決這個問題,你可以移動io_servicefor循環外,也可以在for循環的末端,以調用socket的析構函數,而io_service仍然有效調用conn->sock.reset();

相關問題