2013-07-03 18 views
9

我最近注意到我的應用程序存在問題,我認爲這是由於我沒有正確使用boost::asio,瞭解tcp解析器的功能。用IP和端口解析查詢和創建端點之間的差別

基本上,我使用boost::asio::ip::tcp::resolver來讓端點連接到。

最近我發現它可以提供多個端點(特別是當我連接到本地主機時)。

目前我要求所有終點的async_connect。我不是百分之百肯定,但我認爲這很糟糕。我應該向他們一個請求一個async_connect,等待答覆,並嘗試下一個當且僅當它失敗。

所以基本上知道我有兩個選擇,如果我想使用async_connect這些端點:

  1. 重構我的代碼,這樣我async_connect處理失敗正確,失敗嘗試連接到其他可用端點。我將不得不通過端點迭代器。

  2. 下降解析器和使用端點我建立我自己是這樣的:boost::asio::ip::tcp::endpoint("localhost", 20015)

我種得,我應該使用的第一個解決辦法,分解帶來的東西比自身更多的感覺構建終點。

但是,解析器帶來了什麼?自我構建的終結點如何自我解決?

回答

11

雖然Sam簡潔地回答了大多數應用程序如何處理端點創建,但我想擴展resolver

resolver用於將地址的人類可讀的文本表示形式轉換爲包含用於地址通過定義的表示之間hostname resolution或轉換結構化二進制格式endpoint(一個或多個)。例如,resolver可能會將人類可讀的"localhost"解析爲0x7F000001或將"127.0.0.1"轉換爲0x7F000001。 Boost.Asio使用或模擬getaddrinfo()來執行此解決方案。對於異步解析,將創建一個內部線程來執行操作。

另一方面,basic_endpoint不會自行解析。雖然它不能用字符串和端口構造,但它可以用ip::address和端口構造。所述ip::address可以從點分十進制形式的字符串(IPv4)的或十六進制表示法(IPv6)的構建:

namespace ip = boost::asio::ip; 
ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), 20015); 

提供一個主機名ip::address::from_string()將拋出異常:

namespace ip = boost::asio::ip; 
ip::address::from_string("localhost"); // throws boost::system::system_error 

最後,使用:

  • resolver當你想支持主機名解析或IP轉換。當IP可能改變但主機名保持不變時,或者當單個主機名可能解析爲多個IP時,這特別方便。
  • ip::address::from_string()從IP創建地址。
4

連接到從解析操作返回的所有端點不可能是您的應用程序所期望的。選擇#2將不起作用,因爲basic_endpoint(const char*, int)沒有構造函數。選擇#1是幾個asio示例的結構,特別是async tcp client demonstrating timeouts

重構代碼以包含從解析器返回的endpoint_iterator應該不會太難,如果遇到問題,請按照上面的示例進行操作。請注意,它使用阻止resolve()而不是async_resolve(),但概念是相同的。

+1

感謝您的回答,這是非常有幫助的。然而,我發現使用異步解析是不穩定的(我的平臺是窗口,而且我經常得到'WSA_OPERATION_ABORTED'錯誤'995')。所以我選擇了具有同步解析的中間解決方案和每個端點上的迭代異步連接,並且重構我的代碼非常簡單。 – Arthur

相關問題