boost::asio cleanly disconnecting

你。 提交于 2019-12-02 18:33:57

I think you should probably have a call to socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec) in there before the call to socket.close().

The boost::asio documentation for basic_stream_socket::close states:

For portable behaviour with respect to graceful closure of a connected socket, call shutdown() before closing the socket.

This should ensure that any pending operations on the socket are properly cancelled and any buffers are flushed prior to the call to socket.close.

I have tried to do this with both the close() method and the shutdown() method

socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec)

The shutdown method is the best of the two. However, I find that using the destructor of the ASIO socket is the clean way to do it as ASIO takes care of it all for you. So your goal is to just let the socket fall out of scope. Now, you can do this easily using a shared_ptr and resetting the shared_ptr to a fresh socket or null. this will call the destructor of the ASIO socket and life is good.

Maybe this is what is happening:

  • Client send disconnect packet
  • Client shuts socket down
  • Server read handler gets called, but there is an error associated with the shutdown packet because the socket is already closed.

I see in your read handlers, if there is an error, you never check to see if your shutdown packet is there. Maybe it is. Basically what I'm saying is maybe your client sometimes is able to send both the close and the shutdown packet before the server has a chance to process them separately.

Use async_write() and put socket.close() inside of write handler. This will make sure packet is processed by boost asio and not neglected in the middle of processing (because of close() calls).

I have a very similar issue. I believe it's related to Windows recycling connections. Is the following familiar?

  • you get this error immediately upon starting the program but not after a connection is established?
  • The error never happens if you wait more than 4 minutes before restarting your application?

The tcp specs specify that by default it should wait four minutes for the final acknowledgment when a tcp connection is closed. You can see these connections in FIN_WAIT state using netstat. The Windows OS detects when you try to connect to the exact same system and takes these partially closed connections and recycles them. Your second invocation of the program gets the 'closed' connection left behind by the first run. It gets the next acknowledge and then really closes.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!