情况:我正在运行异步TCP服务器,其中必须同时从客户端进行多个同时连接。在这个特定问题中,我有一个名为tcp_menu_id_receive()
的函数,它接收并返回客户端发送的数值。
问题:函数不等待async_read_some()并立即返回默认值。
int tcp_menu_id_receive()
{
auto self(shared_from_this());
int menuid = 0;
socket_.async_read_some(boost::asio::buffer(data_, max_length), [this, self, &menuid](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
std::string ReceivedData(data_, data_ + length);
menuid = std::stoi(ReceivedData);
std::cout << "!ec menuid: " << menuid << std::endl;
}
});
std::cout << "non !ec menuid: " << menuid << std::endl;
return menuid;
}
问题:如何让`tcp_menu_id_receive'等待客户的数据?
答案 0 :(得分:1)
这实际上是async_read_some
应该做的事情。它将在中间返回调用者,因为它是异步调用。之后,只要事件发生,就会调用回调函数 - io_service
实际管理它。
我认为您希望使用非同步读取,即同步读取,即basic_stream_socket::read_some
方法。
答案 1 :(得分:0)
简而言之,您希望在许多异步操作中同步1个异步操作。
我建议使用非async_
*版本的通话。您声称read_some
并不适合您:
我尝试过read_some,但阻止其他客户端连接 - Chocolate Donut 1 hour ago
我必须说我在这里有点惊讶,但你的代码并不是自包含的,所以我无法复习/尝试重现。
这是&#34; hack&#34;使用deadline_timer
可以用来作为&#34;信号&#34;。平心而论,这意味着现在您同步deadline_timer::wait()
,并且没有真正的理由认为这与同步执行read_some
根本不同。
但是,我的示例 是自包含的,您和我可以测试它/如何 有用。它可能会激发你了解其工作原理,如何修改自己的代码。
#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <iostream>
#include <thread>
namespace ba = boost::asio;
using ba::ip::tcp;
struct X : std::enable_shared_from_this<X> {
X(unsigned short port) {
socket_.connect({{}, port});
std::cout << "connected\n";
}
~X() {
work_.reset();
if (io_thread_.joinable())
io_thread_.join();
}
int tcp_menu_id_receive()
{
auto self(shared_from_this());
int menuid = 0;
std::vector<char> buf(4);
ba::deadline_timer sig(svc_);
sig.expires_at(boost::posix_time::max_date_time);
socket_.async_read_some(boost::asio::buffer(buf), [&, self](boost::system::error_code ec, std::size_t length)
{
std::cout << "Callback: " << ec.message() << "\n";
if (!ec) {
std::string ReceivedData(buf.data(), length);
menuid = std::stoi(ReceivedData);
sig.expires_at(boost::posix_time::min_date_time);
}
sig.cancel(); // just abort
});
// synchronous wait
boost::system::error_code ec;
sig.wait(ec); // ignoring error code
// optionally check result
if (sig.expires_at() == boost::posix_time::max_date_time)
std::cout << "Receive error\n";
return menuid;
}
private:
ba::io_service svc_;
boost::optional<ba::io_service::work> work_{svc_};
std::thread io_thread_ { [this] {
std::cout << "start io_thread_\n";
svc_.run();
std::cout << "exit io_thread_\n";
} };
tcp::socket socket_{svc_};
};
int main() {
auto x = std::make_shared<X>(6767);
std::cout << "DEBUG: menuid: " << x->tcp_menu_id_receive() << "\n";
}
我使用测试服务器在我的机器上测试了它:
echo 2345 | netcat -l -p 6767
输出结果为:
connected
start io_thread_
Callback: Success
DEBUG: menuid: 2345
exit io_thread_