Is detecting a TCP socket disconnect in Python possible?












1















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.










share|improve this question





























    1















    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.










    share|improve this question



























      1












      1








      1








      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.










      share|improve this question
















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 25 '18 at 21:36







      John

















      asked Nov 25 '18 at 19:43









      JohnJohn

      16814




      16814
























          1 Answer
          1






          active

          oldest

          votes


















          3














          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?.






          share|improve this answer
























          • 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











          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
          });


          }
          });














          draft saved

          draft discarded


















          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









          3














          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?.






          share|improve this answer
























          • 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
















          3














          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?.






          share|improve this answer
























          • 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














          3












          3








          3







          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?.






          share|improve this answer













          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?.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 25 '18 at 19:56









          Steffen UllrichSteffen Ullrich

          61.6k358100




          61.6k358100













          • 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

















          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




















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          404 Error Contact Form 7 ajax form submitting

          How to know if a Active Directory user can login interactively

          TypeError: fit_transform() missing 1 required positional argument: 'X'