Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

websocket client doesnt close socket after connetcion close (time_wait connections) #1024

Closed
krsvital opened this issue Feb 16, 2018 · 11 comments

Comments

@krsvital
Copy link

boost beast version 1.67

after compilling this async clien

http://www.boost.org/doc/libs/master/libs/beast/example/websocket/client/async/websocket_client_async.cpp

and i try to connect to

http://www.boost.org/doc/libs/master/libs/beast/example/websocket/server/async/websocket_server_async.cpp

then after close session and after "netstat -na | grep [websocket port]" command, i see time_wait connections like this

tcp 0 0 127.0.0.1:6006 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:6006 127.0.0.1:54280 TIME_WAIT
tcp 0 0 127.0.0.1:6006 127.0.0.1:54282 TIME_WAIT
tcp 0 0 127.0.0.1:6006 127.0.0.1:54279 TIME_WAIT
tcp 0 0 127.0.0.1:6006 127.0.0.1:54284 TIME_WAIT

but if i run websocket client in chrome browser and close the page, time_wait is absent...

@vinniefalco
Copy link
Member

boost beast version 1.67

There is no Boost 1.67 yet, did you mean 1.66? Which version of Beast are you using?

@krsvital
Copy link
Author

I download the last version of boost from github in which incude the beast module

@vinniefalco
Copy link
Member

TIME_WAIT on the server is normal. Your netstat shows "Local address" with port 6006, which I am assuming is the server port. When a TCP/IP connection is shut down, the side initiating the close procedure is left in the TIME_WAIT state. It is preferable for the server to be left with this state than the client (see http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html).

I don't know why Chrome doesn't leave the server with a TIME_WAIT but it could be that it is caching the open connection.

@krsvital
Copy link
Author

if client close connection TIME_WAIT can not be a normal state, becouse server take a "close frame" and close socket by self side, but client side socket doesnt close and client websocket program shutdown without close socket, so TIME_WAIT connections appears in system

when async_close function are finished (websocket_client_async.cpp) client shutdown without close socket by itself

@vinniefalco
Copy link
Member

Beast performs TCP shutdown through the "teardown" mechanism. The server sends a FIN, and then the client responds with a FIN. This should leave the server with the TIME_WAIT state. That code is here:

if(role_ == role_type::server)

and
if(role_ == role_type::client)

However, it looks like there could be a bug in the asynchronous version. Could you please repeat the test using the synchronous client and server and let me know if it operates correctly?

vinniefalco added a commit to vinniefalco/beast that referenced this issue Feb 20, 2018
vinniefalco added a commit to vinniefalco/beast that referenced this issue Feb 20, 2018
@vinniefalco
Copy link
Member

I have implemented a possible fix to the asynchronous teardown code, please try the v157 branch located in my repository:
https://github.com/vinniefalco/beast/commits/v157

@krsvital
Copy link
Author

i repeat the test with standart sync client ( http://www.boost.org/doc/libs/develop/libs/beast/example/websocket/client/sync/websocket_client_sync.cpp )
and with other async websocket server ( rippled ) and with standart ( http://www.boost.org/doc/libs/develop/libs/beast/example/websocket/server/sync/websocket_server_sync.cpp ) server and allways i see TIME_WAIT connections...

@vinniefalco
Copy link
Member

vinniefalco commented Feb 20, 2018

Remember that TIME_WAIT on the server is normal. I'm fairly certain that Beast has the correct behavior here, per https://tools.ietf.org/html/rfc6455#section-5.5.1:

" After both sending and receiving a Close message, an endpoint considers the WebSocket connection closed and MUST close the underlying TCP connection. The server MUST close the underlying TCP connection immediately; the client SHOULD wait for the server to close the connection but MAY close the connection at any time after sending and receiving a Close message, e.g., if it has not received a TCP Close from the server in a reasonable time period."

The rfc prescribes that the server send the FIN first. And this is exactly what Beast does:
https://github.com/vinniefalco/beast/blob/v157/include/boost/beast/websocket/impl/teardown.ipp#L157

@krsvital
Copy link
Author

my problem was solved by set sysctl

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1 ### this value was "0"

thanks for taking the time to my question!

@vinniefalco
Copy link
Member

vinniefalco commented Feb 20, 2018

net.ipv4.tcp_tw_recycle = 1 ### this value was "0"

See https://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux

vinniefalco added a commit to vinniefalco/beast that referenced this issue Feb 20, 2018
vinniefalco added a commit to vinniefalco/beast that referenced this issue Feb 20, 2018
@toddwong
Copy link

toddwong commented Jul 28, 2021

TIME_WAIT on the server is normal. Your netstat shows "Local address" with port 6006, which I am assuming is the server port. When a TCP/IP connection is shut down, the side initiating the close procedure is left in the TIME_WAIT state. It is preferable for the server to be left with this state than the client (see http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html).

I don't know why Chrome doesn't leave the server with a TIME_WAIT but it could be that it is caching the open connection.

but in (http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html)

"For a server that does establish outbound connections as well as accepting inbound connections then the golden rule is to always ensure that if a TIME_WAIT needs to occur that it ends up on the other peer and not the server. The best way to do this is to never initiate an active close from the server, no matter what the reason"

Which do against the recommended closing precedure in WebSocket RFC?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants