{"id":1121,"date":"2013-02-25T10:24:08","date_gmt":"2013-02-25T09:24:08","guid":{"rendered":"https:\/\/www.kolja-engelmann.de\/blog\/?p=1121"},"modified":"2013-02-25T10:25:37","modified_gmt":"2013-02-25T09:25:37","slug":"c-socket-connected-bringt-mich-um-den-verstand-funktioniert-nun-aber","status":"publish","type":"post","link":"https:\/\/www.kolja-engelmann.de\/blog\/2013\/02\/c-socket-connected-bringt-mich-um-den-verstand-funktioniert-nun-aber\/","title":{"rendered":"C# &#8211; Socket.Connected bringt mich um den Verstand, funktioniert nun aber"},"content":{"rendered":"<p>Manchmal braucht man echt viel Vorwissen \u00fcber ein Thema&#8230;hat man es nicht m\u00f6chte man am liebsten seine Maus aufessen. Ich arbeitete mit ein paar Sockets und war der kindlich-naiven \u00dcberzeugung, dass die .NET Property <code>Connected<\/code> mir auch tats\u00e4chlich ausgeben w\u00fcrde, ob mein Socket noch verbunden sei oder nicht. Nope, macht er nicht&#8230;jedenfalls nicht direkt.<\/p>\n<p>.NET \u00fcberpr\u00fcft von sich aus n\u00e4mlich nicht, ob die Verbindung die einem Socket zu Grunde liegt, noch besteht. Stattdessen zeigt <code>Connected<\/code> immer den letzten bekannten Status an, der zum Zeitpunkt der letzten Lese\/Schreiboperation herrschte und beh\u00e4lt diesen bei. So kann es also durch aus sein, dass die Verbindung komplett abbricht, z.B. durch ein gezogenes Kabel und <code>Connected<\/code> zeigt noch immer brav <code>true<\/code> an.<\/p>\n<p>Setzt man sich mit hochrotem Kopf hin und liest sich in dieses Thema ein, stellt man fest, dass dieses Verhalten zwar unlogisch, aber durchaus korrekt ist. TCP ist in diesem Bereich sehr fehlertolerant und st\u00f6rt sich nicht daran, wenn mal eine Verbindung verloren geht. Die logische Verbindung zwischen den zwei Endpunkten k\u00f6nnte durchaus f\u00fcr l\u00e4ngere Zeit physikalisch getrennt und irgendwann wieder hergestellt werden und die Verbindung w\u00fcrde weiterhin bestehen und auch genutzt werden k\u00f6nnen. Einzig ein Timeout (der je nach Betriebssystem anders ist) k\u00f6nnte ein dar\u00fcber liegendes Programm dar\u00fcber informieren, dass seine Verbindung nicht mehr besteht.<\/p>\n<p>Schreibe ich in einen geschlossenen Socket, dann hagelt es nat\u00fcrlich Exceptions. Was kann ich also tun? Ich habe lange im Internet herumgegraben und es gibt wirklich viele verschiedene L\u00f6sungsversuche, die beinahe alle \u00a0wie der folgende erste Codeschnippsel aussehen, der versucht 0 Byte in den Socket zu schreiben \u00a0oder auf irgendwelche ankommenden Pakete zu lauschen.<\/p>\n<pre class=\"lang:c# decode:true\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Checks the connection state\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ &lt;returns&gt;True on connected. False on disconnected.&lt;\/returns&gt;\r\npublic bool IsConnected(Socket pSocket)\r\n{\r\n  if (pSocket.Connected)\r\n  {\r\n    if ((pSocket.Poll(0, SelectMode.SelectWrite)) &amp;&amp; (!pSocket.Poll(0, SelectMode.SelectError)))\r\n    {\r\n      byte[] buffer = new byte[1];\r\n      if (pSocket.Receive(buffer, SocketFlags.Peek) == 0)\r\n      {\r\n        return false;\r\n      }\r\n      else\r\n      {\r\n        return true;\r\n      }\r\n    }\r\n    else\r\n    {\r\n      return false;\r\n    }\r\n  }\r\n  else\r\n  {\r\n    return false;\r\n  }\r\n}<\/pre>\n<p>Leider funktionierte das in meinem Fall einfach mal gar nicht, weil von meiner Gegenstelle keine Daten gesendet werden, die in obiger Funktion h\u00e4tten &#8222;empfangen&#8220; werden k\u00f6nnen. Auch ein heruntersetzen des \u00a0TCP KeepAlive-Pakets\u00a0Intervalls half hier nicht weiter.<\/p>\n<p>Nach langem hin und her, bin ich auf die einfachste und h\u00e4sslichste Methode zur\u00fcckgesprungen: Ich versuche zu schreiben, fange alle Exceptions ab und erhalte daraus den Status meines Sockets.<\/p>\n<pre class=\"lang:c# decode:true\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ For whatever reason every single IsConnected-version I came up with was not working.\r\n\/\/\/ So this is the most elementary version, relying on exceptions\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ &lt;param name=\"pSocket\"&gt;&lt;\/param&gt;\r\n\/\/\/ &lt;returns&gt;True if connected, else false&lt;\/returns&gt;\r\npublic static bool IsConnectedWithExceptions(Socket pSocket)\r\n{\r\n  try\r\n  {\r\n    pSocket.Send(new byte[0]);\r\n    return true;\r\n  }\r\n  catch\r\n  {\r\n    return false;\r\n  }\r\n}<\/pre>\n<p>H\u00e4sslich, schlechter Code, ich hasse mich selbst daf\u00fcr, aber macht verdammt nochmal was er soll!<\/p>","protected":false},"excerpt":{"rendered":"<p>Manchmal braucht man echt viel Vorwissen \u00fcber ein Thema&#8230;hat man es nicht m\u00f6chte man am liebsten seine Maus aufessen. Ich arbeitete mit ein paar Sockets und war der kindlich-naiven \u00dcberzeugung, dass die .NET Property Connected&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":1123,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[38],"tags":[98,39],"class_list":["post-1121","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codeschnippsel","tag-net","tag-c"],"jetpack_featured_media_url":"https:\/\/www.kolja-engelmann.de\/blog\/wp-content\/uploads\/2013\/02\/c-socket-connected-code1.png","jetpack_sharing_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/posts\/1121","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/comments?post=1121"}],"version-history":[{"count":0,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/posts\/1121\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/media\/1123"}],"wp:attachment":[{"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/media?parent=1121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/categories?post=1121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/tags?post=1121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}