Post by Christopher KohlhoffPost by Gancho ManevHi Chris,
I've encountered the same problem...and have managed to workaround it
using reuse_address=true . However that does not treat the problem but
overcome the consequences of improper server stopping. By me the problem
is either OS specific, or we use ASIO in improper way.
1. Open a server (like those in HTTP server example) in a separate thread.
2. Establish a connection to it.
3. Close the acceptor and the socket being waiting on read.
4. Join on the server thread.
5. boost::asio::write(socket, <<some_buffer>>)
- on MS Windows 2000 with ASIO 0.3.7 it works well
-- it leaves a socket in TIME_WAIT state for given time (arroung 20-30
s.), and
The TIME_WAIT state is a normal part of TCP. It is expected behaviour
that if reuse_address is false, you will be unable to start new servers
while there are sockets in TIME_WAIT.
"The TIME_WAIT state is a normal part of TCP" if there is a listening
socket on this port, however I've performed the actions in point 3 (see
above) and even more - the process had ended when I checked the socket
states on Linux - that is suspicious stuff for me.
Post by Christopher KohlhoffWindows is simply taking a shortcut to avoid the TIME_WAIT state if both
the client and server are on the same machine. Evidently Linux does not
take this shortcut.
Post by Gancho Manev-- the point 5 has passed without exception. Nothing received on the
server side!!!
I'm not sure I follow this one. Can you give more detail?
For the test code take a look at fixture_server_launcher and
rpc_integration_tests. The test that fails (the point 5 explained above)
is named "SendInStopTest" - line N 65 in rpc_integration_tests.cpp
On Windows it works correctly raising an exception: "Error during
synchronous send: An existing connection was forcibly closed by the
remote host."
I have attached the following classes:
- template <class SocketStream, class Protocol> class ConnectionImpl; in
my case:
SocketStream = boost::asio::ip::tcp::socket
Protocol = boost::asio::ip::tcp
- RPCServerImpl - particularly focus on "void end()" - delegates end to
the acceptor and gives a callback to cleanup later all already
established connections (through RpcProcessorManager)
- TCPConnectionAcceptor - focus on "void end(EndCallback callback)"
where: typedef boost::function<void ()> EndCallback; - executes the
close sequence (boost::asio::ip::tcp::acceptor::close, next
'callback()') in the Proactor thread
- RpcProcessorManager - looks like the connection_manager in ASIO HTTP
examples
- RpcProcessor - focus on "void stop()". It invokes connection->close()
and thus closes the boost::asio::ip::tcp::socket.
Hope the code is sufficient to catch the case.
Thanks in advance,
Gancho
Post by Christopher Kohlhoff-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/