使用 boost::asio 时的参考问题(我猜)

发布于 2024-11-07 01:07:29 字数 1681 浏览 1 评论 0原文

我正在基于 提升网站。现在,该代码与我的代码之间的区别在于该示例使用服务器构造函数来启动异步操作。这是有道理的,因为服务器应该一直监听。另一方面,在我的客户端中,我想首先构造对象,然后有一个 send() 函数,该函数首先连接到端点,然后发送一个请求,最后侦听回复。这也有道理,不是吗?

当我创建对象(客户端)时,我以与服务器示例(winmain.cpp)相同的方式进行操作。它看起来像这样:

client c("www.boost.org);
c.start(); // starts the io_service in a thread
c.send(msg_);

代码的相关部分如下:

void enabler::send(common::geomessage& msg_)
{
    new_connection_.reset(new connection(io_service_,
        connection_manager_,
        message_manager_, msg_
    ));

    boost::asio::ip::tcp::resolver resolver(io_service_);
    boost::asio::ip::tcp::resolver::query query(host_address, "http");

    resolver.async_resolve(query, boost::bind(
        &enabler::handle_resolve,
        boost::ref(*this),
        boost::asio::placeholders::error,
        boost::asio::placeholders::iterator
    ));
}

void enabler::run()
{
    io_service_.run();
}

问题是程序卡在此处的某个地方。最后打印的是“正在解析主机”,之后程序结束。我不知道为什么,因为 io_service 应该阻塞,直到所有异步操作返回到它们的回调。但是,如果我改变调用函数的顺序,它就会起作用。如果我在调用 async_resolve() 之后立即调用 run(),并且在主程序中省略调用 start(),那么它就可以工作!

在这种情况下,io_service 会按其应有的方式阻塞,并且我可以看到我收到了来自服务器的响应。

这与我从与调用 async_resolve() 相同的类内部调用 run() 的事实有关。这是真的吗?我想当我调用run()时我需要提供主程序的引用,是这样的吗?

我一直在努力让 io_service::work 工作,但程序卡住了,是的,出现了与上述类似的问题。所以它并没有真正的帮助。

那么,我该怎么做才能做到这一点呢?正如我之前所说,我想要的是能够创建客户端对象并让 io_service 始终在客户端类内的单独线程中运行。其次,有一个函数 send(),用于向服务器发送请求。

I am building an HTTP client based on the example on HTTP server given at boost website. Now, the difference between that code and mine is that the example uses the server constructor to start the asynchronous operations. This makes sense since a server is supposed to listen all the time. In my client, on the other hand, I want to first construct the object and then have a send() function that starts off by connecting to the endpoint and later on sends a request and finally listens for the reply. This makes sense too, doesn't it?

When I create my object (client) I do it in the same manner as in the server example (winmain.cpp). It looks like this:

client c("www.boost.org);
c.start(); // starts the io_service in a thread
c.send(msg_);

The relevant parts of the code are these:

void enabler::send(common::geomessage& msg_)
{
    new_connection_.reset(new connection(io_service_,
        connection_manager_,
        message_manager_, msg_
    ));

    boost::asio::ip::tcp::resolver resolver(io_service_);
    boost::asio::ip::tcp::resolver::query query(host_address, "http");

    resolver.async_resolve(query, boost::bind(
        &enabler::handle_resolve,
        boost::ref(*this),
        boost::asio::placeholders::error,
        boost::asio::placeholders::iterator
    ));
}

void enabler::run()
{
    io_service_.run();
}

The problem with this is that the program gets stuck somewhere here. The last thing that prints is the "Resolving host", after that the program ends. I don't know why because the io_service should block until all async operations have returned to their callbacks. If, however, I change the order of how I call the functions, it works. If I call run() just after the call to async_resolve() and also omit calling start() in my main program, it works!

In this scenario, io_service blocks as it should and I can see that I get a response from the server.

It has something to do from the fact that I call run() from inside the same class as where I call async_resolve(). Could this be true? The I suppose I need to give a reference from the main program when I call run(), is it like that?

I have struggled with getting io_service::work to work but the program just gets stuck and yeah, similar problems as the one above occur. So it does not really help.

So, what can I do to get this right? As I said earlier, what I want is to be able to create the client object and have the io_service running all the time in a separate thread inside the client class. Secondly to have a function, send(), that sends requests to the server.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

很快妥协 2024-11-14 01:07:29

在调用 run() 之前,您至少需要开始一些工作,因为当没有更多工作要做时它就会返回。

如果您在启动异步解析之前调用它,它将不会执行任何工作,因此会返回。

You need to start at least some work before calling run(), as it returns when there is no more work to do.

If you call it before you start the async resolve, it won't have any work so it returns.

×纯※雪 2024-11-14 01:07:29

如果您不希望始终有一些工作,为了让 io_service 保持忙碌,您应该在某个范围内构造一个 io_service::work 对象,该对象可以在没有 io_service:: 的情况下退出。 run() 必须首先返回。如果您在单独的线程中运行 io_service ,我想您不会有任何问题。

很难知道你想用这些代码片段做什么。我想你会想做一些类似的事情:

struct client
{
   io_service io_service_;
   io_service::work* w_;
   pthread_t main_thread_;
   client(): w_(new io_service::work(io_service)) { ... }
   void start() { pthread_create(&main_thread_, 0, main_thread, this); }
   static long main_thread(void* arg) { ((client*)arg)->io_service_.run(); }
   // release the io_service and allow run() to return
   void stop() { delete w_; w_ = 0; pthread_join(main_thread_); }
};

If you don't expect to have some work at all times, to keep the io_service busy, you should construct an io_service::work object in some scope which can be exited without io_service::run() having to return first. If you're running the io_service in a separate thread, I would imagine you wouldn't have a problem with that.

It's sort of hard to know what you're trying to do with those snippets of code. I imagine that you'd want to do something along these lines:

struct client
{
   io_service io_service_;
   io_service::work* w_;
   pthread_t main_thread_;
   client(): w_(new io_service::work(io_service)) { ... }
   void start() { pthread_create(&main_thread_, 0, main_thread, this); }
   static long main_thread(void* arg) { ((client*)arg)->io_service_.run(); }
   // release the io_service and allow run() to return
   void stop() { delete w_; w_ = 0; pthread_join(main_thread_); }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文