Why cannot asio tcp socket server detect TCP disconnection when the client device lost power?
Hi, The asio tcp server can detect the disconnection when the client program stop. But I have small device when it lost power, the server won't be able to detect the TCP disconnection. Does the boost socket has TCP timeout? What is an effective way to handle this situation other than running heartbeat in user level? Thank you. Kind regards, - j
On 06/29/2017 06:28 AM, jupiter via Boost-users wrote:
Hi,
The asio tcp server can detect the disconnection when the client program stop. But I have small device when it lost power, the server won't be able to detect the TCP disconnection. Does the boost socket has TCP timeout? What is an effective way to handle this situation other than running heartbeat in user level?
Thank you.
Kind regards,
- j
Well, you could always activate TCP keepalive via socket options and set the corresponding timeout and interval values accordingly. However, it depends on what you want to do really: The TCP keepalive mechanism is something that is implemented by the TCP stack of the operating system and will only check whether the connection is still alive, but that may not be enough because it won't check whether the service you're connected to is actually working/responding. And this is where the application layer heartbeat comes back in. Hope this gives you some idea. Regards, Andreas
Thanks for the response. The server program is calling boost::asio::async_read for waiting for client's data, I am wondering why the async_read didn't fire an error when the remote socket connection is gone. I thought that boost::asio::async_read should detect lost connection. The fact is it does in most of the situations when the client program is ended, but it cannot detect when the client device suddenly lost power connection, I think that might because TCP only send syn / ack during connection / disconnection, the syn/ack would not be active after establishing the connection, correct me if I am wrong here. You are right, if I have to use keep alive, I'll use it in user level which could better control the time and use less bandwidth than the system keep alive. Thank you. Kind regards, - j On Thu, Jun 29, 2017 at 3:09 PM, Andreas Wehrmann via Boost-users < boost-users@lists.boost.org> wrote:
On 06/29/2017 06:28 AM, jupiter via Boost-users wrote:
Hi,
The asio tcp server can detect the disconnection when the client program stop. But I have small device when it lost power, the server won't be able to detect the TCP disconnection. Does the boost socket has TCP timeout? What is an effective way to handle this situation other than running heartbeat in user level?
Thank you.
Kind regards,
- j
Well, you could always activate TCP keepalive via socket options and set the corresponding timeout and interval values accordingly.
However, it depends on what you want to do really: The TCP keepalive mechanism is something that is implemented by the TCP stack of the operating system and will only check whether the connection is still alive, but that may not be enough because it won't check whether the service you're connected to is actually working/responding. And this is where the application layer heartbeat comes back in.
Hope this gives you some idea.
Regards, Andreas
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On 06/29/2017 09:01 AM, jupiter wrote:
Thanks for the response.
The server program is calling boost::asio::async_read for waiting for client's data, I am wondering why the async_read didn't fire an error when the remote socket connection is gone. I thought that boost::asio::async_read should detect lost connection. The fact is it does in most of the situations when the client program is ended, but it cannot detect when the client device suddenly lost power connection, I think that might because TCP only send syn / ack during connection / disconnection, the syn/ack would not be active after establishing the connection, correct me if I am wrong here.
You are right, if I have to use keep alive, I'll use it in user level which could better control the time and use less bandwidth than the system keep alive.
Thank you.
Kind regards,
- j
The TCP connection is usually managed by your operating system (the TCP stack of it, to be precise). When your application suddenly ends or crashes, the operating system will clean up the TCP connections for you (i.e disconnect them) which is the reason why the other end sees an "immediate" disconnect in this case. Tearing down a connection involves specific signalling on the TCP layer (FIN,RST). Now imagine your situation: You have two machines, and both have a TCP connection to each other. When the TCP connection is idle (i.e. nothing is sent between the two) there won't be any signalling on the TCP layer if TCP keep-alive is disabled and there is no application layer heartbeat mechanism. You might already see the problem here: In this situation you won't ever detect whether the other machine is gone, if it suddenly disappeared (i.e. sudden power loss, or some kind of network problem) because: Disconnecting a TCP session or detecting presence always requires some kind of signalling. So, you might already see that this is not a problem specific to asio but to TCP sockets in general. Regards, Andreas
* Andreas Wehrmann via Boost-users
On 06/29/2017 09:01 AM, jupiter wrote:
Thanks for the response.
The server program is calling boost::asio::async_read for waiting for client's data, I am wondering why the async_read didn't fire an error when the remote socket connection is gone. I thought that boost::asio::async_read should detect lost connection. The fact is it does in most of the situations when the client program is ended, but it cannot detect when the client device suddenly lost power connection, I think that might because TCP only send syn / ack during connection / disconnection, the syn/ack would not be active after establishing the connection, correct me if I am wrong here.
You are right, if I have to use keep alive, I'll use it in user level which could better control the time and use less bandwidth than the system keep alive.
Thank you.
Kind regards,
- j
The TCP connection is usually managed by your operating system (the TCP stack of it, to be precise). When your application suddenly ends or crashes, the operating system will clean up the TCP connections for you (i.e disconnect them) which is the reason why the other end sees an "immediate" disconnect in this case. Tearing down a connection involves specific signalling on the TCP layer (FIN,RST).
Now imagine your situation: You have two machines, and both have a TCP connection to each other. When the TCP connection is idle (i.e. nothing is sent between the two) there won't be any signalling on the TCP layer if TCP keep-alive is disabled and there is no application layer heartbeat mechanism.
Implied but not stated here: a TCP keep-alive would be sufficient to notify a server about a client falling off the net, though you may have other reasons to want your own heartbeat messages.
You might already see the problem here: In this situation you won't ever detect whether the other machine is gone, if it suddenly disappeared (i.e. sudden power loss, or some kind of network problem) because: Disconnecting a TCP session or detecting presence always requires some kind of signalling.
So, you might already see that this is not a problem specific to asio but to TCP sockets in general.
Regards, Andreas
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
-- -ericP office: +1.617.599.3509 mobile: +33.6.80.80.35.59 (eric@w3.org) Feel free to forward this message to any list for any purpose other than email address distribution. There are subtle nuances encoded in font variation and clever layout which can only be seen by printing this message on high-clay paper.
On Thu, Jun 29, 2017 at 5:50 PM, Eric Prud'hommeaux
Tearing down a connection involves specific signalling on the TCP layer (FIN,RST).
Now imagine your situation: You have two machines, and both have a TCP connection to each other. When the TCP connection is idle (i.e. nothing is sent between the two) there won't be any signalling on the TCP layer if TCP keep-alive is disabled and there is no application layer heartbeat mechanism.
Implied but not stated here: a TCP keep-alive would be sufficient to notify a server about a client falling off the net, though you may have other reasons to want your own heartbeat messages.
I have a connection map in my server as part of monitoring system to trace down the client connections. If the server can be notified by kernel for a client falling off, that will be good to use a callback errorHandler to clean up the socket connection as well as the connection map automatically. Bandwidth usage is another restriction in my application as the small devices connect by 3G / LTE, anyone knows what is the extra package size for using boost keep alive option? If I have to use heartbeat in user level, I also need deploy a timer / polling mechanism in the server to check missing heartbeat messages then clear the connection and connection map. I don't mind if a client is in idle, but the monitoring system need to detect if a client is connected or not. I don't feel understanding boost socket keepalive option well, I need to explore the boost socket keepalive option more.
jupiter via Boost-users 2017-06-29 15:41: Hi,
I have a connection map in my server as part of monitoring system to trace down the client connections. If the server can be notified by kernel for a client falling off, that will be good to use a callback errorHandler to clean up the socket connection as well as the connection map automatically.
You should inherit the enable_shared_from_this<your session class>, and in async ops in your session class you should use shared_from_this() when start async ops. For monitoring your session you should use map/any_container with weak_ptrs, not shared_ptrs. -- Regards, niXman ___________________________________________________ Dual-target(32 & 64-bit) MinGW-W64 compilers for 32 and 64-bit Windows: https://sf.net/p/mingw-w64/
On Thu, Jun 29, 2017 at 10:51 PM, niXman via Boost-users < boost-users@lists.boost.org> wrote:
You should inherit the enable_shared_from_this<your session class>, and in async ops in your session class you should use shared_from_this() when start async ops.
Yes, I did.
For monitoring your session you should use map/any_container with weak_ptrs, not shared_ptrs.
Interesting, I haven't thought that, what will be the issues and consequences to use shared_ptrs not weak_ptrs? Thanks for your advice.
For monitoring your session you should use map/any_container with weak_ptrs, not shared_ptrs.
Interesting, I haven't thought that, what will be the issues and consequences to use shared_ptrs not weak_ptrs? Thanks for your advice.
Shared pointers keep objects in existence, weak pointers don't. At a price of an additional lock() operation, of course (which, except in really time critical applications, should not be an issue). It's never a good idea to have too many shared pointers around, especially not in the monitoring maps as they may keep objects alive longer than intended. Additional advantage of using weak pointer in monitoring maps is that if the lock() fails it's okay to remove the entry from the map as the object is no longer there. Now, for the sake of being thorough - although weak pointer will not keep the object in existence, it will keep it's shared count alive. Which, in the case of using std::make_shared to allocate shared count and object memory in a single block, will keep the entire block of memory allocated until the last weak pointer is gone ... hence even in the case of using weak pointers it is a good idea to do occasional cleanup, which is rather trivial via failed lock(). Cheers, Leon
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On Fri, Jun 30, 2017 at 10:31 AM, Leon Mlakar via Boost-users < boost-users@lists.boost.org> wrote:
For monitoring your session you should use map/any_container with
weak_ptrs, not shared_ptrs.
Interesting, I haven't thought that, what will be the issues and consequences to use shared_ptrs not weak_ptrs? Thanks for your advice.
Shared pointers keep objects in existence, weak pointers don't. At a price of an additional lock() operation, of course (which, except in really time critical applications, should not be an issue).
It's never a good idea to have too many shared pointers around, especially not in the monitoring maps as they may keep objects alive longer than intended.
Additional advantage of using weak pointer in monitoring maps is that if the lock() fails it's okay to remove the entry from the map as the object is no longer there.
Now, for the sake of being thorough - although weak pointer will not keep the object in existence, it will keep it's shared count alive. Which, in the case of using std::make_shared to allocate shared count and object memory in a single block, will keep the entire block of memory allocated until the last weak pointer is gone ... hence even in the case of using weak pointers it is a good idea to do occasional cleanup, which is rather trivial via failed lock()
Thanks for the explanation, I have more work to do :-) Cheers
Cheers, Leon
On Thu, 2017-06-29 at 15:51 +0300, niXman via Boost-users wrote:
For monitoring your session you should use map/any_container with weak_ptrs, not shared_ptrs.
Especially with networking code, I'd refrain from this. Though it offers a lot of loose coupling, it makes readability difficult. For session bring-down, I always prefer explicit "unregister()" style messages between objects. That way, the "disconnect behaviour" is explicitly embedded in code. IMHO, of course :D -- Joe Steeve HiPro IT Solutions Private Limited http://www.hipro.co.in/
participants (6)
-
Andreas Wehrmann
-
Eric Prud'hommeaux
-
Joe Steeve
-
jupiter
-
Leon Mlakar
-
niXman