Is detecting a TCP socket disconnect in Python possible?
I'm experimenting with Python's socketserver.TCPServer, to see how it works.
I think I have most things figured out, but the one question that remains is how to detect sudden client disconnects, and if it's even possible.
What I've seen so far is that if I write a simple TCPServer, and connect to it with telnet, once telnet disconnects, the TCPServer knows that the client disconnected. Clearly, it gets a TCP message that tells it the client is disconnecting. That's great.
I went one step further, and instead of closing the telnet process on the client, I sent it a SIGKILL, to kill the process without even letting it clean up (tell the server it's disconnecting). Even then, the server knows that the client left right away. It seems that the OS of the client - not the telnet process - sends the TCP FIN/RST message to tell the server the client is gone. Also great.
Next, I went one step beyond that, and while the telnet client was connected to my TCPServer, I told iptables on the client to stop talking to the server. Now, there was absolutely no message being sent to the server to tell it that the client disappeared. At this point, my TCPServer couldn't tell that the client had left.
I know that I can set a socket.setdefaulttimeout() to stop a recv() from blocking indefinitely waiting for a message from the client. The trouble with that is that the timeout will be triggered if the client just stays quiet for a while (doesn't send the server any messages), or if the client disappears all of a sudden.
So my question is this: when a socket is connected between a server and a client, and the client disappears completely, without sending a TCP FIN or RST, does the server have any way of knowing that the client is gone (as opposed to still there, but not sending any messages)? Or is having some sort of heartbeat that the client would stop responding to the main way to tell that the client is gone?
I read somewhere that TCP has keepalive built into the protocol, but that the normal timeout for that is set by the OS, not adjustable, and is hours, and should not be relied upon.
While I'm currently working with Python, I imagine this is more of a generic networking question than Python-specific.
Update: For anyone interested, this is what I ended up with. There's a few improvements that could be made, like adding if __name__ == "__main__"
, and handling messages longer than 1024 bytes, but as far as letting clients connect, and detecting if they disappear, it seems to work pretty well.
python sockets networking
add a comment |
I'm experimenting with Python's socketserver.TCPServer, to see how it works.
I think I have most things figured out, but the one question that remains is how to detect sudden client disconnects, and if it's even possible.
What I've seen so far is that if I write a simple TCPServer, and connect to it with telnet, once telnet disconnects, the TCPServer knows that the client disconnected. Clearly, it gets a TCP message that tells it the client is disconnecting. That's great.
I went one step further, and instead of closing the telnet process on the client, I sent it a SIGKILL, to kill the process without even letting it clean up (tell the server it's disconnecting). Even then, the server knows that the client left right away. It seems that the OS of the client - not the telnet process - sends the TCP FIN/RST message to tell the server the client is gone. Also great.
Next, I went one step beyond that, and while the telnet client was connected to my TCPServer, I told iptables on the client to stop talking to the server. Now, there was absolutely no message being sent to the server to tell it that the client disappeared. At this point, my TCPServer couldn't tell that the client had left.
I know that I can set a socket.setdefaulttimeout() to stop a recv() from blocking indefinitely waiting for a message from the client. The trouble with that is that the timeout will be triggered if the client just stays quiet for a while (doesn't send the server any messages), or if the client disappears all of a sudden.
So my question is this: when a socket is connected between a server and a client, and the client disappears completely, without sending a TCP FIN or RST, does the server have any way of knowing that the client is gone (as opposed to still there, but not sending any messages)? Or is having some sort of heartbeat that the client would stop responding to the main way to tell that the client is gone?
I read somewhere that TCP has keepalive built into the protocol, but that the normal timeout for that is set by the OS, not adjustable, and is hours, and should not be relied upon.
While I'm currently working with Python, I imagine this is more of a generic networking question than Python-specific.
Update: For anyone interested, this is what I ended up with. There's a few improvements that could be made, like adding if __name__ == "__main__"
, and handling messages longer than 1024 bytes, but as far as letting clients connect, and detecting if they disappear, it seems to work pretty well.
python sockets networking
add a comment |
I'm experimenting with Python's socketserver.TCPServer, to see how it works.
I think I have most things figured out, but the one question that remains is how to detect sudden client disconnects, and if it's even possible.
What I've seen so far is that if I write a simple TCPServer, and connect to it with telnet, once telnet disconnects, the TCPServer knows that the client disconnected. Clearly, it gets a TCP message that tells it the client is disconnecting. That's great.
I went one step further, and instead of closing the telnet process on the client, I sent it a SIGKILL, to kill the process without even letting it clean up (tell the server it's disconnecting). Even then, the server knows that the client left right away. It seems that the OS of the client - not the telnet process - sends the TCP FIN/RST message to tell the server the client is gone. Also great.
Next, I went one step beyond that, and while the telnet client was connected to my TCPServer, I told iptables on the client to stop talking to the server. Now, there was absolutely no message being sent to the server to tell it that the client disappeared. At this point, my TCPServer couldn't tell that the client had left.
I know that I can set a socket.setdefaulttimeout() to stop a recv() from blocking indefinitely waiting for a message from the client. The trouble with that is that the timeout will be triggered if the client just stays quiet for a while (doesn't send the server any messages), or if the client disappears all of a sudden.
So my question is this: when a socket is connected between a server and a client, and the client disappears completely, without sending a TCP FIN or RST, does the server have any way of knowing that the client is gone (as opposed to still there, but not sending any messages)? Or is having some sort of heartbeat that the client would stop responding to the main way to tell that the client is gone?
I read somewhere that TCP has keepalive built into the protocol, but that the normal timeout for that is set by the OS, not adjustable, and is hours, and should not be relied upon.
While I'm currently working with Python, I imagine this is more of a generic networking question than Python-specific.
Update: For anyone interested, this is what I ended up with. There's a few improvements that could be made, like adding if __name__ == "__main__"
, and handling messages longer than 1024 bytes, but as far as letting clients connect, and detecting if they disappear, it seems to work pretty well.
python sockets networking
I'm experimenting with Python's socketserver.TCPServer, to see how it works.
I think I have most things figured out, but the one question that remains is how to detect sudden client disconnects, and if it's even possible.
What I've seen so far is that if I write a simple TCPServer, and connect to it with telnet, once telnet disconnects, the TCPServer knows that the client disconnected. Clearly, it gets a TCP message that tells it the client is disconnecting. That's great.
I went one step further, and instead of closing the telnet process on the client, I sent it a SIGKILL, to kill the process without even letting it clean up (tell the server it's disconnecting). Even then, the server knows that the client left right away. It seems that the OS of the client - not the telnet process - sends the TCP FIN/RST message to tell the server the client is gone. Also great.
Next, I went one step beyond that, and while the telnet client was connected to my TCPServer, I told iptables on the client to stop talking to the server. Now, there was absolutely no message being sent to the server to tell it that the client disappeared. At this point, my TCPServer couldn't tell that the client had left.
I know that I can set a socket.setdefaulttimeout() to stop a recv() from blocking indefinitely waiting for a message from the client. The trouble with that is that the timeout will be triggered if the client just stays quiet for a while (doesn't send the server any messages), or if the client disappears all of a sudden.
So my question is this: when a socket is connected between a server and a client, and the client disappears completely, without sending a TCP FIN or RST, does the server have any way of knowing that the client is gone (as opposed to still there, but not sending any messages)? Or is having some sort of heartbeat that the client would stop responding to the main way to tell that the client is gone?
I read somewhere that TCP has keepalive built into the protocol, but that the normal timeout for that is set by the OS, not adjustable, and is hours, and should not be relied upon.
While I'm currently working with Python, I imagine this is more of a generic networking question than Python-specific.
Update: For anyone interested, this is what I ended up with. There's a few improvements that could be made, like adding if __name__ == "__main__"
, and handling messages longer than 1024 bytes, but as far as letting clients connect, and detecting if they disappear, it seems to work pretty well.
python sockets networking
python sockets networking
edited Nov 25 '18 at 21:36
John
asked Nov 25 '18 at 19:43
JohnJohn
16814
16814
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
It is perfectly fine for TCP connections to not transfer any kind of data for a long time. And it is also not a problem if a cable gets disconnected as long as it is reconnected later data need to be transmitted.
The only way to be sure that the peer is still reachable is to have some kind of heartbeat. This can be either be done at the application level or it can be done at the TCP level - using TCP keep-alive. Usually systems offer a way to not only enable TCP keep-alive per socket but also to adjust how often a keep-alive packet will be send when the socket is idle, i.e. how quick an application can find out that the peer is no longer there. To get to the details on how to do this in Python see How to change tcp keepalive timer using python script?.
Thanks for the great explanation. Usingset_keepalive_linux()
from the link you included worked great. It can tell if the client is just being quiet, or if the client disappeared without any application-level heartbeat code - just a bit of code to set the TCP timeout values.
– John
Nov 25 '18 at 20:42
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53471205%2fis-detecting-a-tcp-socket-disconnect-in-python-possible%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
It is perfectly fine for TCP connections to not transfer any kind of data for a long time. And it is also not a problem if a cable gets disconnected as long as it is reconnected later data need to be transmitted.
The only way to be sure that the peer is still reachable is to have some kind of heartbeat. This can be either be done at the application level or it can be done at the TCP level - using TCP keep-alive. Usually systems offer a way to not only enable TCP keep-alive per socket but also to adjust how often a keep-alive packet will be send when the socket is idle, i.e. how quick an application can find out that the peer is no longer there. To get to the details on how to do this in Python see How to change tcp keepalive timer using python script?.
Thanks for the great explanation. Usingset_keepalive_linux()
from the link you included worked great. It can tell if the client is just being quiet, or if the client disappeared without any application-level heartbeat code - just a bit of code to set the TCP timeout values.
– John
Nov 25 '18 at 20:42
add a comment |
It is perfectly fine for TCP connections to not transfer any kind of data for a long time. And it is also not a problem if a cable gets disconnected as long as it is reconnected later data need to be transmitted.
The only way to be sure that the peer is still reachable is to have some kind of heartbeat. This can be either be done at the application level or it can be done at the TCP level - using TCP keep-alive. Usually systems offer a way to not only enable TCP keep-alive per socket but also to adjust how often a keep-alive packet will be send when the socket is idle, i.e. how quick an application can find out that the peer is no longer there. To get to the details on how to do this in Python see How to change tcp keepalive timer using python script?.
Thanks for the great explanation. Usingset_keepalive_linux()
from the link you included worked great. It can tell if the client is just being quiet, or if the client disappeared without any application-level heartbeat code - just a bit of code to set the TCP timeout values.
– John
Nov 25 '18 at 20:42
add a comment |
It is perfectly fine for TCP connections to not transfer any kind of data for a long time. And it is also not a problem if a cable gets disconnected as long as it is reconnected later data need to be transmitted.
The only way to be sure that the peer is still reachable is to have some kind of heartbeat. This can be either be done at the application level or it can be done at the TCP level - using TCP keep-alive. Usually systems offer a way to not only enable TCP keep-alive per socket but also to adjust how often a keep-alive packet will be send when the socket is idle, i.e. how quick an application can find out that the peer is no longer there. To get to the details on how to do this in Python see How to change tcp keepalive timer using python script?.
It is perfectly fine for TCP connections to not transfer any kind of data for a long time. And it is also not a problem if a cable gets disconnected as long as it is reconnected later data need to be transmitted.
The only way to be sure that the peer is still reachable is to have some kind of heartbeat. This can be either be done at the application level or it can be done at the TCP level - using TCP keep-alive. Usually systems offer a way to not only enable TCP keep-alive per socket but also to adjust how often a keep-alive packet will be send when the socket is idle, i.e. how quick an application can find out that the peer is no longer there. To get to the details on how to do this in Python see How to change tcp keepalive timer using python script?.
answered Nov 25 '18 at 19:56
Steffen UllrichSteffen Ullrich
61.6k358100
61.6k358100
Thanks for the great explanation. Usingset_keepalive_linux()
from the link you included worked great. It can tell if the client is just being quiet, or if the client disappeared without any application-level heartbeat code - just a bit of code to set the TCP timeout values.
– John
Nov 25 '18 at 20:42
add a comment |
Thanks for the great explanation. Usingset_keepalive_linux()
from the link you included worked great. It can tell if the client is just being quiet, or if the client disappeared without any application-level heartbeat code - just a bit of code to set the TCP timeout values.
– John
Nov 25 '18 at 20:42
Thanks for the great explanation. Using
set_keepalive_linux()
from the link you included worked great. It can tell if the client is just being quiet, or if the client disappeared without any application-level heartbeat code - just a bit of code to set the TCP timeout values.– John
Nov 25 '18 at 20:42
Thanks for the great explanation. Using
set_keepalive_linux()
from the link you included worked great. It can tell if the client is just being quiet, or if the client disappeared without any application-level heartbeat code - just a bit of code to set the TCP timeout values.– John
Nov 25 '18 at 20:42
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53471205%2fis-detecting-a-tcp-socket-disconnect-in-python-possible%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown