views:

169

answers:

3

In the following code:

tcp::socket socket(io_service);
tcp::endpoint ep(boost::asio::ip::address::from_string(addr), i);


socket.async_connect(ep, &connect_handler);

socket.close();

is it correct to close the socket object, or should I close it only in the connect_handler(), resort to shared_ptr to prolong the life of of the socket object? Thanks.

A: 

It is safe. The connect_handler will give you ec == boost::asio::error::connection_aborted. Of course, you need to do io_service.run() for the handler to be invoked.

thanks, does it mean, when asyn_* operations are involved, you almost always need to dynamically create a socket(with shared_prt<socket> to prolong its lifetime) so that it won't get closed due to the object's staying out of scope?
t.g.
+1  A: 

As already answered by Chila, it's safe to close the socket whenever you want. If the socket in question has an outstanding operation at the time, the handler/callback will be invoked to notify you've cancelled the operation. That's where connection_aborted shows up.

As for your question about shared_ptr, I consider it a big win if you have another thread or other objects referencing your sockets, however, it isn't required in many cases. All you have to do is to dynamically allocate them, and deallocate when they're no longer needed. Of course, if you have other objects or threads referencing your socket, you must update them prior to delete/dealloc. Doing so, you avoid invalid memory access because the object pointed by them no longer exists (see dangling pointer).

jweyrich
thank you for the response, it does answer my question. Unfortunately I can only accept one answer.
t.g.
+1  A: 

Closing the socket isn't much of an issue, but the socket being destructed and deallocated is. One way to deal with it is to just make sure the socket outlives the io_service where work is being done. In other words, you just make sure to not delete it until after the io_service has exited. Obviously this won't work in every situation.

In a variety of conditions it can be difficult to impossible to tell when all work is really done on the socket when it's active within the io_service, and ASIO doesn't provide any mechanism to explicitly remove or disconnect the object's callbacks so they don't get called. So you should consider holding the connection in a shared_ptr, which will keep the connection object until the last reference inside the io_service has been released.

Meanwhile your handler functors should handle all possible errors passed in, including the connection being destroyed.

karunski
Thanks for the answer, esp. This line: "Closing the socket isn't much of an issue, but the socket being destructed and deallocated is". Sometime you just need someone to point out one little thing, and everything else seems so clear suddenly. this is the case.
t.g.