{"id":3902,"date":"2013-12-15T09:38:25","date_gmt":"2013-12-15T08:38:25","guid":{"rendered":"https:\/\/www.kolja-engelmann.de\/blog\/?p=3902"},"modified":"2014-05-19T09:07:58","modified_gmt":"2014-05-19T07:07:58","slug":"verbindungsstatus-eines-sockets-feststellen-teil-2","status":"publish","type":"post","link":"https:\/\/www.kolja-engelmann.de\/blog\/2013\/12\/verbindungsstatus-eines-sockets-feststellen-teil-2\/","title":{"rendered":"C# &#8211; Verbindungsstatus eines Sockets feststellen &#8211; Teil 2"},"content":{"rendered":"<p>Ich schrieb schon zuvor einmal dar\u00fcber, wie ich den <a title=\"C# \u2013 Socket.Connected bringt mich um den Verstand, funktioniert nun aber\" href=\"https:\/\/www.kolja-engelmann.de\/blog\/2013\/02\/c-socket-connected-bringt-mich-um-den-verstand-funktioniert-nun-aber\/\">Verbindungsstatus eines C#-Sockets \u00fcberpr\u00fcfe<\/a>. W\u00e4hrend der Testphase eines neuen Projekts, bei dem ich viele Mobilger\u00e4te gleichzeitig \u00fcber verschiedene Mobilfunktechnologien steuere, musste ich periodisch \u00fcberpr\u00fcfen, ob die verbundenen Clients \u00fcberhaupt noch ansprechbar waren oder nicht. Also nutzte ich meine erprobte <code>IsConnected<\/code>-Methode und staunte nicht schlecht, als mir Code steif und fest behauptete, dass meine Verbindung noch best\u00fcnde, obwohl die Gegenstelle zu Testzwecken komplett ausgeschaltet wurde. Ich konnte sogar Daten in den Socket schreiben, ohne dass es Fehler hagelte. Klasse.<\/p>\n<p>Ich erspare euch jetzt die wortreiche Beschreibung wie ich tagelang auf den Code starrte und meine Fingern\u00e4gel rillen im Tisch hinterlie\u00dfen und mache es kurz: Erst nachdem ich das <code>KeepAlive<\/code>-Sendeintervall des Sockets drastisch heruntersetzte, funktionierte auch wieder meine <code>IsConnected<\/code>-\u00dcberpr\u00fcfung wieder.<\/p>\n<p>Hierzu fand ich im Internet die folgende Extension-Methode die, einmal im Namespace geladen, ihre Funktionalit\u00e4t jedem Socket-Objekt zur Verf\u00fcgung stellt.<\/p>\n<pre class=\"lang:default decode:true\">namespace System.Net.Sockets\r\n{\r\n  public static class SocketExtensions\r\n  {\r\n    private const int BytesPerLong = 4; \/\/ 32 \/ 8\r\n    private const int BitsPerByte = 8;\r\n\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Sets the keep-alive interval for the socket.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    \/\/\/ &lt;param name=\"socket\"&gt;The socket.&lt;\/param&gt;\r\n    \/\/\/ &lt;param name=\"time\"&gt;Time between two keep alive \"pings\".&lt;\/param&gt;\r\n    \/\/\/ &lt;param name=\"interval\"&gt;Time between two keep alive \"pings\" when first one fails.&lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;If the keep alive infos were succefully modified.&lt;\/returns&gt;\r\n    public static bool SetKeepAlive(this Socket socket, ulong time, ulong interval)\r\n    {\r\n      try\r\n      {\r\n        \/\/ Array to hold input values.\r\n        var input = new[]\r\n        {\r\n          (time == 0 || interval == 0) ? 0UL : 1UL, \/\/ on or off\r\n          time,\r\n          interval\r\n        };\r\n\r\n        \/\/ Pack input into byte struct.\r\n        byte[] inValue = new byte[3 * BytesPerLong];\r\n        for (int i = 0; i &lt; input.Length; i++)\r\n        {\r\n          inValue[i * BytesPerLong + 3] = (byte)(input[i] &gt;&gt; ((BytesPerLong - 1) * BitsPerByte) &amp; 0xff);\r\n          inValue[i * BytesPerLong + 2] = (byte)(input[i] &gt;&gt; ((BytesPerLong - 2) * BitsPerByte) &amp; 0xff);\r\n          inValue[i * BytesPerLong + 1] = (byte)(input[i] &gt;&gt; ((BytesPerLong - 3) * BitsPerByte) &amp; 0xff);\r\n          inValue[i * BytesPerLong + 0] = (byte)(input[i] &gt;&gt; ((BytesPerLong - 4) * BitsPerByte) &amp; 0xff);\r\n        }\r\n\r\n        \/\/ Create bytestruct for result (bytes pending on server socket).\r\n        byte[] outValue = BitConverter.GetBytes(0);\r\n\r\n        \/\/ Write SIO_VALS to Socket IOControl.\r\n        socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);\r\n        socket.IOControl(IOControlCode.KeepAliveValues, inValue, outValue);\r\n      }\r\n      catch (SocketException e)\r\n      {\r\n        Console.WriteLine(\"Failed to set keep-alive: {0} {1}\", e.ErrorCode, e);\r\n        return false;\r\n      }\r\n\r\n      return true;\r\n    }\r\n  }\r\n}<\/pre>\n<p>Die Benutzung des Codes ist sehr einfach:<\/p>\n<pre class=\"lang:c# decode:true\">\/\/Create socket\r\nvar _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);\r\n\/\/Connect to any host\r\n_socket.Connect(IPAddress.Parse(\"127.0.0.1\"), 80);\r\n\/\/Set KeepAlive\r\n_socket.SetKeepAlive(250, 100);<\/pre>\n<p>Mein Fazit? \u00a0Ich muss dringend von den Sockets wegkommen und etwas nutzen das mehr &#8222;High-level&#8220; ist. Wenn ich weiterhin mit Sockets arbeite ist das einzige was &#8222;High-level&#8220; ist nur mein Blutdruck.<\/p>","protected":false},"excerpt":{"rendered":"<p>Ich schrieb schon zuvor einmal dar\u00fcber, wie ich den Verbindungsstatus eines C#-Sockets \u00fcberpr\u00fcfe. W\u00e4hrend der Testphase eines neuen Projekts, bei dem ich viele Mobilger\u00e4te gleichzeitig \u00fcber verschiedene Mobilfunktechnologien steuere, musste ich periodisch \u00fcberpr\u00fcfen, ob die&#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-3902","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\/3902","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=3902"}],"version-history":[{"count":0,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/posts\/3902\/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=3902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/categories?post=3902"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kolja-engelmann.de\/blog\/wp-json\/wp\/v2\/tags?post=3902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}