I have a asio sync connection. ioService is in one thread (I have only one thread.).
Smaller problem:
boost::asio::async_write(m_socket, boost::asio::buffer(requestStr.data(), requestStr.size()), handler);
The handler is never called, but the server gets it and replies that I get.
The bigger problem:
boost::asio::async_read_until(m_socket, sbuf, '\n', sendingHandler);
It also doesn't call the handler. The sbuf is immediately filled and I can read it there, but I don't know the position of the deliminator. Therefore I need the handler to get the bytes_transferred parameter. (I'm not going to iterate the buffer.)
I tried several things and I could invoke the handler once, but I don't remember what the issue was about after a small refract. Any help? Thanks!
When I used sync messaging, everything was fine, but there is no timeout there.
EDIT:
If you know any nice solution to find the deliminator I don't need the handler.
Because, I would send the msg sync_write and read async.
It wont be called, because it is async. Async methods for writing and reading never call handlers from within the place they're called:
Regardless of whether the asynchronous operation completes immediately
or not, the handler will not be invoked from within this function.
Invocation of the handler will be performed in a manner equivalent to
using boost::asio::io_service::post().
You need to manually call io_service methods like run or run_once to perform operations and that is the moment when your callback will be called.
Related
I am trying to use boost:asio library to create a threadpool. The official documentation says :
dispatch : Request the io_service to invoke the given handler.
post: Request the io_service to invoke the given handler and return immediately.
Could someone explain how these two differ ?
The difference is dispatch may run handler (the CompletionHandler passed to it) inside it which means you will wait for it to finish, if it does, before the function returns. post on the other hand will not run handler itself and returns back to the call site immediately.
So, dispatch is a potentially blocking call while post is a non-blocking call.
Post ensures that the thread that calls post will not immediately attempt to process the task.
https://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/io_service/post.html
but without allowing the io_service to call the handler from inside
this function.
Dispatch makes no such promise; and may be completed by the time the function returns.
I am quite new in boost::asio and I have a problem. I am writting client that sends in loop some commands to server. I am sending command with boost::asio::async_write and I expect that every time I send commands handler will be called. In fact only during first sending I see that handler is called. My client looks like that:
Client::Client(boost::asio::io_service & p_ioService,
boost::asio::ip::tcp::endpoint p_endpoint)
: io_service(p_ioService), endpoint(p_endpoint), socket(p_ioService)
{
socket.connect(endpoint);
}
Client::~Client()
{
socket.close();
}
void Client::sendCommand(const string & p_command)
{
boost::asio::async_write(socket,boost::asio::buffer(p_command),
boost::bind(&Client::onSendingFinished,this, _1, _2));
io_service.run();
}
void Client::onSendingFinished(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
cout<<"Sent "<<bytes_transferred<<endl;
}
There is no other place in main.cpp where io_service.run is called. I notice that if I call
io_service.reset() after io_service.run() it works fine, handler is called every time.
How should I solve this without io_service.reset()
Thanks in advance
I do not understand the aversion to calling io_service::reset(). In this case, it is necessary to invoke prior to any subsequent calls to io_service::run():
reset() must be called prior to any second or later set of invocations of the run(), run_one(), poll() or poll_one() functions when a previous invocation of these functions returned due to the io_service being stopped or running out of work.
It is possible that a thread returns from run() as a result of an exception being thrown, yet the io_service has neither been stopped nor ran out of work. In this case, the thread can invoke run() without calling reset().
The current Client::sendCommand() is synchronous. It is an implementation detail that it initiates an asynchronous operation, then blocks in io_service::run() waiting for the operation to complete. Unless there are multiple threads invoking commands on socket, multiple threads running the io_service, or the write operation needs to be cancellable, such as from a timeout, then it would be functionally equivalent and possible easier to implement Client::sendCommand() with a synchronous write().
void Client::sendCommand(const string & p_command)
{
boost::system::error_code ec;
std::size_t bytes_transferred =
boost::asio::write(socket, boost::asio::buffer(p_command), ec);
onSendingFinished(ec, bytes_transferred);
}
If Client::sendCommand() needs to be asynchronous, then:
The io_service should be ran from outside of Client::sendCommand(). If the io_service does not always have outstanding work, then io_service::work can be used control when run() returns. See this answer for more details as to when io_service::run() blocks and unblocks.
The underlying memory provided to async_write() as the buffer (p_command) needs to remain valid until the operation's handler, Client::onSendingFinished(), has been called. In this case, it may require making a copy of p_command in Client::sendCommand(), writing the copy to the socket, then deleting the copy from within the handler.
[...] ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.
While it is not inherently bad to call reset() every now and then, there are two typical ways to avoid having to do it.
Start a new async operation within the handler of the first one. run() only returns once all handlers have finished and thus a new async operation started in a handler is still in time to keep blocking io_service.
Use io_service::work. If you create an instance of io_service::work constructed with your io_service as parameter, than your subsequent calls to run() will not return as long as the work object remains alive. And thus you will not have to reset anything. Of course this means that either one of your handlers or another thread has to destroy the work object at some time, if you want run() to ever stop blocking.
It's quite unusual to just send messages, it's far more common to have two way communication.
If you implemented a receiver as well, then your receive code would always require a receive handler running in the io_service and you wouldn't have this problem...
I have this situation:
void foo::bar()
{
RequestsManager->SendRequest(someRequest, this, &foo::someCallback);
}
where RequestsManager works in asynchronous way:
SendRequest puts the request in a queue and returns to the caller
Other thread gets the requests from the queue and process them
When one request is processed the callback is called
Is it possible to have foo::someCallback called in the same thread as SendRequest? If not, how may I avoid following "callback limitation": callbacks should not make time consuming operations to avoid blocking the requests manager.
No - calls/callbacks cannot change thread context - you have to issue some signal to communicate between threads.
Typically, 'someCallback' would either signal an event upon which the thread that originated the 'SendRequest' call is waiting on, (synchronous call), or push the SendRequest, (and so, presumably, results from its processing), onto a queue upon which the thread that originated the 'SendRequest' call will eventually pop , (asynchronous). Just depends on how the originator wshes to be signaled..
Aynch example - the callback might PostMessage/Dispatcher.BeginInvoke the completed SendRequest to a GUI thread for display of the results.
I can see few ways how to achieve it:
A) Implement strategy similar to signal handling
When request processing is over RequestManager puts callback invocation on the waiting list. Next time SendRequest is called, right before returning execution it will check are there any pending callbacks for the thread and execute them. This is relatively simple approach with minimal requirements on the client. Choose it if latency is not of a concern. RequestManager can expose API to forcefully check for pending callbacks
B) Suspend callback-target thread and execute callback in the third thread
This will give you true asynchronous solution with all its caveats. It will look like target-thread execution got interrupted and execution jumped into interrupt handler. Before callback returns target thread needs to be resumed. You wont be able to access thread local storage or original thread's stack from inside the callback.
Depends on "time-consuming operations"'s definition.
The classic way to do this is:
when the request is processed, the RequestManager should execute that &foo::someCallback
to avoid blocking the request manager, you may just rise a flag inside this callback
check that flag periodically inside the thread, which called RequestsManager->SendRequest
This flag will be just a volatile bool inside class foo
If you want to make sure, that the calling thread (foo's) will understand immediately, that the request has been processed, you need additional synchronization.
Implement (or use already implemented) blocking pipe (or use signals/events) between these threads. The idea is:
foo's thread executes SendRequest
foo starts sleeping on some select (for example)
RequestManager executes the request and:
calls &foo::someCallback
"awakes" the foo's thread (by sending something in that file descriptor, which foo sleeps on (using select))
foo is awaken
checks the volatile bool flag for already processed request
does what it needs to do
annuls the flag
I am trying to receive data from a server application using boost asio's async_read() free function, but the callback I set for when the receiving is never called.
The client code is like this:
Client::Client()
{
m_oIoService.run(); // member boost::asio::io_service
m_pSocket = new boost::asio::ip::tcp::socket(m_oIoService);
// Connection to the server
[...]
// First read
boost::asio::async_read(*m_pSocket,
boost::asio::buffer((void*)&m_oData, sizeof(m_oData)),
boost::bind(&Client::handleReceivedData, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
I tried with small data (a short string) and I can't get it to work. When I use the synchronous read function (boost::asio::read()) using the two same first parameters, everything works perfectly.
Am I missing something with the use of the io_service? I am still unsure about how it works.
boost::asio::service::run () is a blocking call. Now, in your example it may or may not return immediately. In case it doesn't, you you are blocked even before you create a socket, and never call read, so cannot expect a callback. Otherwise, dispatch loop is exited, so no callbacks are ever delivered.
Read more about boost::asio::service::run (). I recommend you check out documentation including tutorial, examples and reference. It is worth going trough it in full to understand the concept.
Hope it helps!
P.S.: On a side note, your code is not exception safe. Beware that if constructor of the class fails with exception then destructor of that class instance is never called. Thus, you may leak at least m_pSocket if its type is not one of the "smart pointers". You should consider making it exception safe, moving the code to another method that should be called by user, or even wrapping this functionality with a free function.
I've an application to which a GUI connects and receives a lot of messages and the problem is that every once in a while it receives a message out of order.
The connection runs on a separate worker thread (a separate io_service) and exposes the send function(which does a async__write) via io_service::wrap as a callback for others to invoke with a string message as parameter. (i.e. callback = io_service_.wrap(boost::bind(&SomeGUIClass::send,this,_1));),
so to send something to the GUI client, the others call callback(stringMessage) - which should correctly dispatch the send function call on the io_service's queue.
messages are in correct order before invoking the callback, but I can see that sometimes they are out of order within the callback,just before the write call.
my reasoning: wrap translates to a dispatch which will try to call the wrapped fn. within the callback (if it can meet the thread safety guarantees) , and schedule it for later if it cannot.
thus sometimes earlier messages get scheduled for a later write and the latest messages get processed since dispatch was able to process it within the same callback.
please let me know if this reasoning is correct, any ideas appreciated.
thanks!
it was a bug, and thus the attendant confusion. (was making the mistake of calling io_service::run from 2 separate threads wihout realising.) now realized, and problem solved. thanks!