Есть, например, этот код:
int main() {
boost::asio::io_service service;
auto work = boost::asio::make_work_guard(service);
boost::asio::ip::tcp::socket socket{ service };
boost::asio::io_service::strand strand{ service };
std::string address{ "192.168.1.13" };
std::string port{ "8002" };
boost::asio::streambuf input{512};
boost::asio::thread_pool pool(1);
boost::asio::post(pool, [&service]()
{
try {
service.run();
}
catch (...)
{
::std::cout << "Catch" << ::std::endl;
}
}
);
auto lambda = [&input](auto er, auto tr) {
if (!er) {
::std::cout << tr << ::std::endl;
::std::istream st{ &input };
::std::string target;
for (unsigned int i = 0; i < tr; ++i)
target += st.get();
}
else {
::std::cout << er.message() << ::std::endl;
}
};
socket.async_connect(
{
boost::asio::ip::make_address(address),
boost::lexical_cast<unsigned short>(port)
},
boost::asio::bind_executor(
strand,
[](auto& er) {
if (!er)
::std::cout << "Success" << ::std::endl;
else {
::std::cout << "Error" << ::std::endl;
}
}
)
);
boost::asio::async_read_until(
socket,
input,
"/r/n",
boost::asio::bind_executor(
strand,
lambda
)
);
boost::asio::async_read_until(
socket,
input,
"/r/n",
boost::asio::bind_executor(
strand,
lambda
)
);
work.reset();
pool.join();
service.stop();
return 0;
}
И вывод из asio:
@asio|1550142117.477501|0*1|thread_pool@00E2FB60.post
@asio|1550142117.477501|>1|
@asio|1550142117.535496|0*2|socket@00E2FC24.async_connect
@asio|1550142117.536498|0*3|socket@00E2FC24.async_receive
@asio|1550142117.536498|0*4|socket@00E2FC24.async_receive
@asio|1550142117.536498|>3|ec=system:10057,bytes_transferred=0
@asio|1550142117.536498|3*5|strand@00E46A68.dispatch
@asio|1550142117.536498|>5|
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
@asio|1550142117.537497|<5|
@asio|1550142117.537497|<3|
@asio|1550142117.537497|>4|ec=system:10057,bytes_transferred=0
@asio|1550142117.537497|4*6|strand@00E46A68.dispatch
@asio|1550142117.537497|>6|
A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
@asio|1550142117.537497|<6|
@asio|1550142117.537497|<4|
@asio|1550142117.537497|>2|ec=system:0
@asio|1550142117.537497|2*7|strand@00E46A68.dispatch
@asio|1550142117.537497|>7|
Success
@asio|1550142117.537497|<7|
@asio|1550142117.537497|<2|
@asio|1550142127.536385|<1|
Вопрос: На каком основании async_read_until
выполняется раньше async_connect
и как мне это избежать? boost::asio::io_service::strand
отказывается помогать.
Дополнение: Я нашел причину в документации Strand -
Note that in the following case:
async_op_1(..., s.wrap(a)); async_op_2(..., s.wrap(b));
the completion of the first async operation will perform s.dispatch(a), and the second will perform s.dispatch(b), but the order in which those are performed is unspecified. That is, you cannot state whether one happens-before the other. Therefore none of the above conditions are met and no ordering guarantee is made.
Но от это не легче.
Оставшийся вопрос: Как мне это избежать, не меняя вышестояющую последовательность, т.е. последовательно вызывать async_* команды и выполнять их только в той последовательности?
UDP: Путем углубленного анализа документации, что надо было делать с самого начала, я понял, что async_* функции имеют несколько этапов и их не следует вызывать в одном потоке. Но это не сказано для async_connect в сокете. Проблема опережения чтения также осталась неизвестной.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Есть некий framework, в котором парсится командная срокаСтрока имеет вид: --file=simple
недавно начал пользоваться JavaConfig в SpringИ сейчас решил попировать провести тесты, без использования xml
Есть задача: Необходимо написать класс который сериализует/десериализует Java BeansВ случае наличия циклических ссылок выкинуть exception