[Asio]What's the behavior of socket.async_write() after socket.close() is called?
Hi, If I call socket.close() but I still have some data in my buffer, can I call async_write() later? When I call socket.close(), maybe an async_write operation is running, when it's complete I want to send data in another buffer(data written while previous async_write() is running, before socket.close() was called), but the socket is closed.Does it work in this situation?If not, what's the alternative way? The code looks like this: char front_buffer[kBufferSize]; char back_buffer[kBufferSize]; void HandleWrite(...) { //socket is closed. Does this work? socket.async_write(back_buffer, ...); } socket.async_write(front_buffer, HandleWrite); // write data to back_buffer socket.close();
If I call socket.close() but I still have some data in my buffer, can I call async_write() later?
Obviously, you can't perform i/o on a closed socket.
When I call socket.close(), maybe an async_write operation is running, when it's complete I want to send data in another buffer(data written while previous async_write() is running, before socket.close() was called), but the socket is closed.Does it work in this situation?If not, what's the alternative way?
You can't write to a closed socket. Connect the socket again, then write to it anything you wish.
void HandleWrite(...) { //socket is closed. Does this work? socket.async_write(back_buffer, ...); }
No.
socket.async_write(front_buffer, HandleWrite); // write data to back_buffer socket.close();
In this case some data might be sent, and some might be not.
bad designed api. close() does not need to be public -- it belongs into the destructor.
"?æ½?é£??û"
wrote in message news:AANLkTin6DuWYwIWpf6GAK4TL98drUZ3Q0zsNoomOtfum@mail.gmail.com... Hi, If I call socket.close() but I still have some data in my buffer, can I call async_write() later? When I call socket.close(), maybe an async_write operation is running, when it's complete I want to send data in another buffer(data written while previous async_write() is running, before socket.close() was called), but the socket is closed.Does it work in this situation?If not, what's the alternative way? The code looks like this: char front_buffer[kBufferSize]; char back_buffer[kBufferSize];
void HandleWrite(...) { //socket is closed. Does this work? socket.async_write(back_buffer, ...); }
socket.async_write(front_buffer, HandleWrite); // write data to back_buffer socket.close();
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
bad designed api. close() does not need to be public -- it belongs into the destructor.
Usually socket destruction is the consequence of its closing. How would you emulate the following scheme, if it wouldn't be possible to close a socket? // pseudo-code struct connection : enable_shared_from_this<connection> { void read() { async_read(socket_, buffer_, bind(&read_handler, shared_from_this(), _1, _2); } void close() { socket_.close(); } private: tcp::socket socket_; };
On Mon, Jun 7, 2010 at 6:54 AM, Igor R
bad designed api. close() does not need to be public -- it belongs into the destructor.
Usually socket destruction is the consequence of its closing. How would you emulate the following scheme, if it wouldn't be possible to close a socket?
You would destroy the socket. Delete'ing it, or using a boost::optional. [snipped example] Regards, -- Felipe Magno de Almeida
You would destroy the socket. Delete'ing it,
So it would be always necessary to store a ptr to a socket? Then delete the socket, which was passed by reference to async_read()? Doesn't sound good, does it?
or using a boost::optional.
But it's not optional, according to its semantics...
On Mon, Jun 7, 2010 at 7:17 AM, Igor R
You would destroy the socket. Delete'ing it,
So it would be always necessary to store a ptr to a socket? Then delete the socket, which was passed by reference to async_read()? Doesn't sound good, does it?
I see. You would call cancel first. Unfortunately cancelling is not very reliable. But cancelling is what is conceptually right here IMHO.
or using a boost::optional.
But it's not optional, according to its semantics...
It seems to me. If you call close you want the socket released. That a zombie socket remains is a design problem. Zombie objects should be avoided. I don't think it can be implementable without unnecessary overhead though. Regards, -- Felipe Magno de Almeida
Sorry to answer myself,
On Mon, Jun 7, 2010 at 7:26 AM, Felipe Magno de Almeida
On Mon, Jun 7, 2010 at 7:17 AM, Igor R
wrote: You would destroy the socket. Delete'ing it,
So it would be always necessary to store a ptr to a socket? Then delete the socket, which was passed by reference to async_read()? Doesn't sound good, does it?
I see. You would call cancel first. Unfortunately cancelling is not very reliable. But cancelling is what is conceptually right here IMHO.
Also, the destructor guarantees to cancel any pending asynchronous operation AFAIK. So it isn't a problem AFAIU. Unless you have multithreading issues, which would be a problem with close as well. [snip] -- Felipe Magno de Almeida
It seems to me. If you call close you want the socket released. That a zombie socket remains is a design problem. Zombie objects should be avoided.
Why is it more zombie, than a fresh "unopened" socket?
Also, the destructor guarantees to cancel any pending asynchronous operation AFAIK.
As far as I can see, it doesn't. shutdown() does.
On Mon, Jun 7, 2010 at 8:03 AM, Igor R
It seems to me. If you call close you want the socket released. That a zombie socket remains is a design problem. Zombie objects should be avoided.
Why is it more zombie, than a fresh "unopened" socket?
It is not. A open function is also bad. Two-phase construction is not well seen, and with reason. They loosen the classes invariant and make reasoning harder.
Also, the destructor guarantees to cancel any pending asynchronous operation AFAIK.
As far as I can see, it doesn't. shutdown() does.
IIRC, the destructor calls shutdown. But I can't see any documentation for tcp::socket destructor. Maybe Christopher could shed us some light in this. I hope it is just an overlook. Obligating everybody to call shutdown before destroying a socket with pending asynchronous operations seems dangerous to me. Regards, -- Felipe Magno de Almeida
Felipe,
I guess it is MUST be mode/state in the socket when all pending recv
operations are canceled and new recv calls are rejected BUT socket handle is
still alive. Using this mode user can safely shutdown incoming data
processing. Otherwise user should lock socket before call
async_read/close/async_write.
On 7 June 2010 13:26, Felipe Magno de Almeida
On Mon, Jun 7, 2010 at 7:17 AM, Igor R
wrote: You would destroy the socket. Delete'ing it,
So it would be always necessary to store a ptr to a socket? Then delete the socket, which was passed by reference to async_read()? Doesn't sound good, does it?
I see. You would call cancel first. Unfortunately cancelling is not very reliable. But cancelling is what is conceptually right here IMHO.
or using a boost::optional.
But it's not optional, according to its semantics...
It seems to me. If you call close you want the socket released. That a zombie socket remains is a design problem. Zombie objects should be avoided. I don't think it can be implementable without unnecessary overhead though.
Regards, -- Felipe Magno de Almeida _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Dmytro Ovdiienko e-mail: dmitriy.ovdienko@gmail.com skype: dmitriy.ovdienko@gmail.com mobile: +38050-1909731
participants (5)
-
Dmytro Ovdiienko
-
Felipe Magno de Almeida
-
Igor R
-
Peter Foelsche
-
鑫炜廖