我想檢查Boost Asio
是否確實執行異步連接。根據the diagrams corresponding to the asynchronous calls發佈在Asio
的基礎知識,當io_service
向操作系統發出信號時開始操作,因此我明白,在執行async.connect
指令後,系統嘗試執行該連接。在GNU/Linux下,async_connect真的是異步的嗎?
我知道的是,如果你不打電話run
你只是錯過了結果,但操作可能完成。所以我試着用nc -l -p 9000
創建一個虛擬服務器,然後使用下面的代碼。
使用調試器,我已發表聲明並且在run
調用io_service
之前停止了。在服務器中,沒有任何反應。沒有關於連接 - 這是顯而易見的,因爲虛擬服務器不會告訴你關於它的信息 - 也不是async_write
。
在調用run
函數後立即在服務器端彈出相應的消息。我一直在詢問Boost
的IRC頻道,並在顯示我的strace
後,一位真正聰明的人告訴我,這可能是因爲在調用run
之前插座還沒有準備好。顯然,這不會發生在Windows上。
這是否意味着在GNU/Linux操作系統下異步並不是真正的異步?這是否意味着網站上顯示的圖表不符合GNU/Linux環境?
注:關於「是不是真的異步」:是的,它不會阻塞調用,因此該線程保持運行,做的事情,但我由開始的操作,他們已經被執行之後意味着異步。
非常感謝您提前。
代碼
#include <iostream>
#include <string.h>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
void connect_handler(const boost::system::error_code& error)
{
if(error)
{
std::cout << error.message() << std::endl;
exit(EXIT_FAILURE);
}
else
{
std::cout << "Successfully connected!" << std::endl;
}
}
void write_handler(const boost::system::error_code& error)
{
if(error)
{
std::cout << error.message() << std::endl;
exit(EXIT_FAILURE);
}
else
{
std::cout << "Yes, we wrote!" << std::endl;
}
}
int main()
{
boost::asio::io_service io_service;
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::ip::tcp::endpoint endpoint(
boost::asio::ip::address::from_string("127.0.0.1"), 9000);
socket.async_connect(endpoint, connect_handler);
std::string hello_world("Hello World!");
boost::asio::async_write(socket, boost::asio::buffer(hello_world.c_str(),
hello_world.size()), boost::bind(write_handler,
boost::asio::placeholders::error));
io_service.run();
exit(EXIT_SUCCESS);
}
我strace的
futex(0x7f44cd0ca03c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f44cd0ca048, FUTEX_WAKE_PRIVATE, 2147483647) = 0
eventfd2(0, O_NONBLOCK|O_CLOEXEC) = 3
epoll_create1(EPOLL_CLOEXEC) = 4
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC) = 5
epoll_ctl(4, EPOLL_CTL_ADD, 3, {EPOLLIN|EPOLLERR|EPOLLET, {u32=37842600, u64=37842600}}) = 0
write(3, "\1\0\0\0\0\0\0\0", 8) = 8
epoll_ctl(4, EPOLL_CTL_ADD, 5, {EPOLLIN|EPOLLERR, {u32=37842612, u64=37842612}}) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 6
epoll_ctl(4, EPOLL_CTL_ADD, 6, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET, {u32=37842704, u64=37842704}}) = 0
ioctl(6, FIONBIO, [1]) = 0
connect(6, {sa_family=AF_INET, sin_port=htons(9000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
epoll_ctl(4, EPOLL_CTL_MOD, 6, {EPOLLIN|EPOLLPRI|EPOLLOUT|EPOLLERR|EPOLLHUP|EPOLLET, {u32=37842704, u64=37842704}}) = 0
epoll_wait(4, {{EPOLLIN, {u32=37842600, u64=37842600}}, {EPOLLOUT, {u32=37842704, u64=37842704}}}, 128, -1) = 2
poll([{fd=6, events=POLLOUT}], 1, 0) = 1 ([{fd=6, revents=POLLOUT}])
getsockopt(6, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
sendmsg(6, {msg_name(0)=NULL, msg_iov(1)=[{"Hello World!", 12}], msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL) = 12
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 5), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f44cd933000
write(1, "Successfully connected!\n", 24Successfully connected!
) = 24
epoll_wait(4, {}, 128, 0) = 0
write(1, "Yes, we wrote!\n", 15Yes, we wrote!
) = 15
exit_group(0) = ?
+++ exited with 0 +++
「執行後立即啓動操作」不是「異步」的標準含義。您可能需要閱讀[boost.asio基本原理頁面](http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/overview/rationale.html),其中描述了該庫的用途。 – Sneftel
謝謝@Sneftel,謝謝你的回答。我在該頁面閱讀,特別是_「Boost.Asio提供了管理這些長時間運行操作的工具,而無需程序使用基於線程和顯式鎖定的併發模型。」_部分。但是,如果我正確理解了鏈接狀態圖,那麼連接信號在執行connect語句後立即發送。這是最讓我困惑的部分。 – MikelAlejoBR
啊,我看到了這個問題。我會更詳細地回答。 – Sneftel